【题意】给出一个无向图,每个点有一个标号mark[i],不同点可能有相同的标号。对于一条边(u, v),它的权值定义为mark[u] xor mark[v]。现在一些点的标号已定,请决定剩下点的标号,使得总的边权和最小。(0 < N <= 500, 0 <= M <= 3000, 0 <= mark[i] <= 2^31-1)

胡伯涛神牛《最小割模型在信息学竞赛中的应用》中的例题。非常好的一道题!非常推荐!

【思路】

我们把问题数学化就是:  Minimum  sigma(we) = sigma(u, v)∈E ( mark(u) xor mark(v) )

对于异或问题,我们发现这样的二进制按位运算各个二进制位之间是互不影响的,所以我们可以一位一位的做这类题。

那么我们的式子又可以进一步转化为:

Minimum  sigma(u, v)∈E { sigmai=0~oo(2^i) • sigma(mark(u, i) xor mark(v, i)) }

这样我们就把mark的限制加强了:只可能是0或1。即这些点将分成两类。

再观察我们发现,xor运算,只有当u、v不同时结果才为1,即这样的有效边的两端点一定属于不同点集。这像什么?不就是割边嘛!~而题目正好又是要求最小,这样问题便转化为最小割了~    (要注意培养这种问题转化和模型发现的能力!)

那么具体的最小割网络GN模型:建一个源点,向每一个标号为1的点连一条oo流量的边(后面解释为什么源点连标号1的点);建一个汇点,向每一个标号为0的点连一条oo流量的边;原图中的边容量设为1加入到GN中。求出来的最小割便是该二进制位下的标号xor的和最小的情况。

然而题目还要求输出所有点的标号,并且需要标号的和也最小。那么怎么保证标号的和最小呢?无非就是尽可能的取0。那么又该怎么做?

首先先看怎么给那些未标号的点标号:容易想到最小割把网络分成了两个点集,那么显然每个点标号应该和它所在点集已标号的点一致,所以当然希望标号为0的点集点更多一些。然后注意我们划分点集是从源点开始dfs,那么这样划出来的最小割边集显然更偏向源点,即这样划分出来的S集点是最少的。于是源点当然连标号为1的点呐~

【代码】

#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)/2)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXV = 505;
const int MAXE = 10005;
const int oo = 0x3fffffff;

/* Dinic-2.0-2013.07.21: adds template. double & int 转换方便多了,也不易出错 ~*/
template
struct Dinic{
struct node{
int u, v;
T flow;
int opp;
int next;
}arc[2*MAXE];
int vn, en, head[MAXV];
int cur[MAXV];
int q[MAXV];
int path[2*MAXE], top;
int dep[MAXV];
void init(int n){
vn = n;
en = 0;
mem(head, -1);
}
void insert_flow(int u, int v, T flow){
arc[en].u = u;
arc[en].v = v;
arc[en].flow = flow;
arc[en].next = head[u];
head[u] = en ++;

arc[en].u = v;
arc[en].v = u;
arc[en].flow = 0;
arc[en].next = head[v];
head[v] = en ++;
}
bool bfs(int s, int t){
mem(dep, -1);
int lq = 0, rq = 1;
dep[s] = 0;
q[lq] = s;
while(lq 0){
dep[v] = dep[u] + 1;
q[rq ++] = v;
}
}
}
return false;
}
T solve(int s, int t){
T maxflow = 0;
while(bfs(s, t)){
int i, j;
for (i = 1; i arc[path[k]].flow){
minflow = arc[path[k]].flow;
mink = k;
}
for (int k = 0; k dinic;
int mark[MAXV];
bool if_mark[MAXV];
struct path{
int u, v;
}p[MAXE];
bool vis[MAXV];
int st[MAXV]; //ST集
void dfs(int u){
vis[u] = 1;
st[u] = 1;
for (int i = dinic.head[u]; i != -1; i = dinic.arc[i].next){
if (dinic.arc[i].flow

SPOJ-OPTM Optimal Marks ★★(按位建图 && 最小割)的更多相关文章

  1. 【bzoj2400】Spoj 839 Optimal Marks 按位最大流

    Spoj 839 Optimal Marks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 908  Solved: 347[Submit][Stat ...

  2. 图论(网络流):SPOJ OPTM - Optimal Marks

    OPTM - Optimal Marks You are given an undirected graph G(V, E). Each vertex has a mark which is an i ...

  3. SPOJ OPTM - Optimal Marks

    OPTM - Optimal Marks no tags  You are given an undirected graph G(V, E). Each vertex has a mark whic ...

  4. BZOJ 2400: Spoj 839 Optimal Marks (按位最小割)

    题面 一个无向图,一些点有固定权值,另外的点权值由你来定. 边的值为两点的异或值,一个无向图的值定义为所有边的值之和. 求无向图的最小值 分析 每一位都互不干扰,按位处理. 用最小割算最小值 保留原图 ...

  5. hdu 5294 Tricks Device 最短路建图+最小割

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 Tricks Device Time Limit: 2000/1000 MS (Java/Other ...

  6. Luogu SP839 OPTM - Optimal Marks(按位最小割)

    这道题和 BZOJ 2400 是一道题,不多讲了 CODE #include <cstdio> #include <cstring> #include <vector&g ...

  7. BZOJ 1475 & 1324 && 建图最小割

    题意: 给一个矩阵,取其中一方格中的数,满足所有所取方格不相邻. SOL: 典型一个二分图,染色后不相邻的连边即可.跑个最大流,裸裸哒. Code: 代码没什么时间写了...并不是很想贴...都是贴板 ...

  8. 【BZOJ2400】Spoj 839 Optimal Marks 最小割

    [BZOJ2400]Spoj 839 Optimal Marks Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. ...

  9. SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)

    http://www.spoj.com/problems/OPTM/ 题意: 给出一张图,点有点权,边有边权 定义一条边的权值为其连接两点的异或和 定义一张图的权值为所有边的权值之和 已知部分点的点权 ...

随机推荐

  1. xml学习总结(一)

    xml DTD 定义元素<!ELEMENT 元素名 元素类型描述 > (1)元素类型描述:任意类型,字符串型,空元素,包含子元素,混合类型 任意类型: <?xml version=& ...

  2. 在iframe结构中,如何使弹出层位于所有框架的上方(-)

    在做后台管理页面的时候,经常用到iframe.虽说这东西有些过时,也不利于SEO,但是后台就是后台,不需要考虑那么多东西,综合来说,用iframe还是很适合后台管理界面的. 但是在遇到弹出层时,出现了 ...

  3. Perl内置变量速查表

    [ 文件句柄 ] $| 如果非零, 则在对当前选定的文件执行写或打印操作后强制清除缓冲区 $% 当前选中文件句柄的当前页码 $= 当前选中文件句柄的当前页面长度 $- 当前选中文件句柄的页面剩余长度 ...

  4. HDFS导论(转)

    1.流式数据访问 HDFS的构建思想是这样的:一次写入,多次读取是最高效的访问模式.数据集通常有数据源生成或从数据源复制而来,接着长时间在此数据集上进行各类分析.每次分析都将设计数据集的大部分数据甚至 ...

  5. How to open MS word document from the SharePoint 2010 using Microsoft.Office.Interop.dll

    or this you must change the identity of word component inC:\windows\System32\comexp.mscto be interac ...

  6. 机器学习基石的泛化理论及VC维部分整理

    第四讲 机器学习的可行性 一.Hoeffding's Inequality \(P[\left | \nu -\mu  \right |>\epsilon ] \leq 2exp(-2\epsi ...

  7. 域名的a记录转过来他的公网ip

    首先 客户要我把域名 和项目进行绑定客户需要提供万网或者新网的账户,登进去域名管理  选项域名管理的A记录定向到那个公网ip上 与服务器做绑定然后 在服务器的iis 上 加个主机头 输入主机头名称 也 ...

  8. having——至少被订购过两回的订单

    此篇介绍having的用法 一.表:订单表,产品表 说明:订单表order ,包含prodectid 二.查询至少被订购过两回的订单 800x600 Normal 0 7.8 磅 0 2 false ...

  9. org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.chen.vo.Dept.parentId

    异常描述:执行以下的addAsHaveParentId2方法出现此异常: /*-----------------------类Dept.Dept.hbm.xml有parentId属性(数据库中有此列) ...

  10. linux命令useradd添加用户详解

    1.作用 useradd或adduser命令用来建立用户帐号和创建用户的起始目录,使用权限是超级用户. 2.格式 useradd [-d home] [-s shell] [-c comment] [ ...