SP839 Optimal marks(最小割)
SP839 Optimal marks(最小割)
给你一个无向图G(V,E)。 每个顶点都有一个int范围内的整数的标记。 不同的顶点可能有相同的标记。对于边(u,v),我们定义Cost(u,v)= mark [u] \(\oplus\) mark [v]。现在我们知道某些节点的标记了。你需要确定其他节点的标记,以使边的总成本尽可能小。(0 < N <= 500, 0 <= M <= 3000)
先来看一下异或的性质,由于每一位是独立的,我们可以把每一位拉出来分开考虑,变成32个子问题。
现在问题就变成了:一堆点是0,一堆点是1,一堆点没有标号,它们互相有一些边,一个边的权值只当一个点是0一个点是1时才是1,否则是0。求最小边权和
于是我们这样建图:(红色表示1,蓝色表示0,白色表示没有权值)

然后跑一个最小割即可。脑补一下,就是找出红色点势力和蓝色点势力的接触处的最小边数。
关于最小割建模的题,具体怎么操作,首先是定义割的含义,就是和s相连的点都定义成要选择的点,其它的点都不选择。关于边的值的定义,不能割的边设置成INF。这个算是套路。
由于题目要求点权和最小,因此我们应尽量让红色点最少。于是,跑完最大流以后,把从s能遍历到的点都标成1就可以满足红色点最少啦!(这个不会证,留坑。)
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=505, maxm=3005, INF=1e9;
int T, n, m, k, src, dst;
inline int min(int x, int y){ return x<y?x:y; }
struct Edge{
int to, nxt, f;
}e[maxm*2+maxn], e1[maxm];
int fir[maxn], cnte;
void addedge(int x, int y, int v){
Edge &ed=e[++cnte];
ed.to=y; ed.nxt=fir[x]; ed.f=v; fir[x]=cnte; }
void RESET(){ cnte=1; memset(fir, 0, sizeof(fir)); }
int mark[maxn], gmark[maxn];
int dep[maxn], q[maxn], head, tail;
int bfs(){ //bfs来给图分层
head=tail=0; memset(dep, 0, sizeof(dep));
dep[src]=1; q[tail++]=src; int tmp;
while (head<tail){
tmp=q[head++];
for (int i=fir[tmp]; i>0; i=e[i].nxt)
if (e[i].f>0&&!dep[e[i].to]){
dep[e[i].to]=dep[tmp]+1;
q[tail++]=e[i].to;
}
}
return dep[dst]?1:0;
}
int cur[maxn];
int dfs(int u, int flow){ //flow表示从s流到当前点的最大流量 找出一条流
if (u==dst) return flow;
if (cur[u]==-1) return 0;
for (int i=(cur[u]?cur[u]:fir[u]); i>0; i=e[i].nxt){
cur[u]=i;
if (dep[e[i].to]==dep[u]+1&&e[i].f){
int minm=dfs(e[i].to, min(flow, e[i].f));
if (minm>0){
e[i].f-=minm; e[i^1].f+=minm;
return minm;
}
}
}
cur[u]=-1;
return 0;
}
void dinic(){
while (bfs()){
memset(cur, 0, sizeof(cur));
while (dfs(src, INF));
}
}
bool vis[maxn];
void findzero(int u){
vis[u]=true;
for (int i=fir[u]; i; i=e[i].nxt){
if (vis[e[i].to]||!e[i].f) continue;
findzero(e[i].to);
}
}
int uu[maxm], vv[maxm];
int main(){
scanf("%d", &T); int t;
while (T--){
scanf("%d%d", &n, &m); dst=n+1;
for (int i=0; i<m; ++i)
scanf("%d%d", &uu[i], &vv[i]);
scanf("%d", &k);
memset(mark, 0, sizeof(mark));
memset(gmark, 0, sizeof(gmark));
for (int i=1; i<=k; ++i){
scanf("%d", &t); gmark[t]=1;
scanf("%d", &mark[t]);
}
for (int i=0; i<31; ++i){
RESET();
for (int j=0; j<m; ++j)
addedge(uu[j], vv[j], 1), addedge(vv[j], uu[j], 1);
for (int j=1; j<=n; ++j){
if (!gmark[j]) continue;
if (mark[j]&(1<<i)) addedge(src, j, INF);
else addedge(j, dst, INF);
}
dinic();
memset(vis, 0, sizeof(vis)); findzero(src);
for (int j=1; j<=n; ++j)
if (vis[j]) mark[j]|=(1<<i);
}
for (int i=1; i<=n; ++i) printf("%d\n", mark[i]);
}
return 0;
}
SP839 Optimal marks(最小割)的更多相关文章
- 【BZOJ2400】Spoj 839 Optimal Marks 最小割
[BZOJ2400]Spoj 839 Optimal Marks Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. ...
- 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS
2400: Spoj 839 Optimal Marks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 567 Solved: 202[Submit ...
- [SP839]Optimal Marks
luogu 题意 给你一个无向图\(G(V,E)\). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记. 对于边\((u,v)\),我们定义\(Cost(u,v)=\rm ma ...
- SPOJ839 Optimal Marks(最小割)
题目大概说给一张图,每个点都有权,边的权等于其两端点权的异或和,现已知几个点的权,为了使所有边的边权和最小,其他点的权值该是多少. 很有意思的一道题,完全看不出和网络流有什么关系. 考虑每个未知的点$ ...
- spoj 839 Optimal Marks(二进制位,最小割)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17875 [题意] 给定一个图,图的权定义为边的两端点相抑或值的 ...
- SPOJ-OPTM Optimal Marks ★★(按位建图 && 最小割)
[题意]给出一个无向图,每个点有一个标号mark[i],不同点可能有相同的标号.对于一条边(u, v),它的权值定义为mark[u] xor mark[v].现在一些点的标号已定,请决定剩下点的标号, ...
- SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)
http://www.spoj.com/problems/OPTM/ 题意: 给出一张图,点有点权,边有边权 定义一条边的权值为其连接两点的异或和 定义一张图的权值为所有边的权值之和 已知部分点的点权 ...
- SPOJ 839 Optimal Marks(最小割的应用)
https://vjudge.net/problem/SPOJ-OPTM 题意: 给出一个无向图G,每个点 v 以一个有界非负整数 lv 作为标号,每条边e=(u,v)的权w定义为该边的两个端点的标号 ...
- Optimal Marks SPOJ - OPTM (按位枚举-最小割)
题意:给一张无向图,每个点有其点权,边(i,j)的cost是\(val_i\ XOR \ val_j\).现在只给出K个点的权值,求如何安排其余的点,使总花费最小. 分析:题目保证权值不超过32位整型 ...
随机推荐
- 深入VR之前 你应该知道VR头显透镜原理
转自:http://www.gamelook.com.cn/2016/03/246817 要理解虚拟现实头显透镜的工作原理,首先要搞懂眼睛是如何看到事物的. 眼睛瞳孔后有晶状体,也就是眼珠子.眼睛的背 ...
- UTF-8, Unicode, GB2312格式串转换之C语言版
原住址:http://www.cnitblog.com/wujian-IT/archive/2007/12/13/37671.html /* author: wu.j ...
- ALTER PROFILE DEFAULT LIMIT PASS_LIFE_TIME UNLIMITED
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_T ...
- 2015.3.5 VS2005调用VC6 dll 时结构参数的传递
结构只能以地址方式进行传递,dll只能传递结构不能传递类 VS端: [DllImport(@"D:\程序\VC程序\MfcDllspace\Debug\space.dll")] p ...
- hadoop 更改 tmp目录
配置hadoop临时目录--------------------- 1.配置[core-site.xml]文件 <configuration> <property> <n ...
- HTML标签详细讲解
http://www.cnblogs.com/yuanchenqi/articles/5603871.html
- Ajax笔记(一)
Ajax三步骤: Asynchronous Javascript And XML 1.运用HTML和CSS实现页面,表达信息: 2.运用XMLHttpRequest和web服务器进行数据的异步交换: ...
- 在JAVA中,String,Stringbuffer,StringBuilder 的区别
首先是,String,StringBuffer的区别 两者的主要却别有两方面,第一是线程安全方面,第二是效率方面 线程安全方面: String 不是线程安全的,这意味着在不同线程共享一个String ...
- gym - 101673I Twenty Four, Again (表达式树枚举)
题意及思路 模拟场上用一般方法枚举非常麻烦,一个小时没写出来,还是自己太菜了...用表达式树枚举有一个好处,判断需不需要加括号非常方便,只有当前节点运算符的优先级高于子节点的时候,才需要给子节点加一个 ...
- python struct.pack中的对齐字节问题
最近测试涉及到了序列字节化相关问题,碰到一个头疼的问题 buff = struct.pack("3s","B00") print repr(buff) 输 ...