传送门

闵神讲网络流应用的例题,来水一水

要写出这道题,需要深入理解两个概念,异或和最小割。

异或具有相对独立性,所以我们把每一位拆开来看,即做大概$32$次最小割。然后累加即可。

然后是最小割把一张图分割成两个集合,简单看就是0集合和1集合。

简单的建图:

原图不变,改成双向边,所有的流量限制为1。然后所有S点向点权为1的连边,点权为0的向T连边,容量都是正无穷。

为什么这样建?首先看,最小割把一张图分成两个点集。而因为我们的流量限制可以让最小割只割真实存在的边,而割的也只有可能是跨越0集合和1集合的边。所以最后的最小割就是答案。

//SPOJ839
//by Cydiater
//2017.1.15
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <queue>
#include <map>
#include <algorithm>
#include <cstring>
#include <string>
#include <bitset>
#include <set>
#include <vector>
using namespace std;
#define ll long long
#define up(i,j,n)	for(int i=j;i<=n;i++)
#define down(i,j,n)	for(int i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
#define Auto(i,node)	for(int i=LINK[node];i;i=e[i].next)
#define vci 		vector<int>
const int MAXN=1e4+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int LINK[MAXN],len=0,N,M,Val[MAXN],TT,Q,tag[MAXN],S,T,ans=0,q[MAXN],head,tail,level[MAXN];
bool used[MAXN],vis[MAXN];
vci E[MAXN];
struct edge{
	int x,y,next,flow,reverse;
}e[MAXN<<1];
namespace solution{
	void Clear(){
		len=0;
		memset(LINK,0,sizeof(LINK));
	}
	inline void insert(int x,int y,int flow,int delta){
		e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;
		e[len].flow=flow;e[len].reverse=len+delta;
	}
	void Prepare(){
		Clear();
		N=read();M=read();
		S=N+1;T=N+2;
		up(i,1,N)E[i].clear();
		up(i,1,M){
			int x=read(),y=read();
			E[x].push_back(y);
			E[y].push_back(x);
		}
		Q=read();
		memset(Val,0,sizeof(Val));
                memset(used,0,sizeof(used));
		while(Q--){
			int node=read(),val=read();
			Val[node]=val;used[node]=1;
		}
	}
	void Build(){
		Clear();
		up(i,1,N){
			int siz=E[i].size();
			up(j,0,siz-1){
				insert(i,E[i][j],1,1);
				insert(E[i][j],i,0,-1);
			}
		}
		up(i,1,N){
			if(tag[i]==1){
				insert(S,i,oo,1);
				insert(i,S,0,-1);
			}else if(tag[i]==0){
				insert(i,T,oo,1);
				insert(T,i,0,-1);
			}
		}
	}
	bool makelevel(){
		memset(level,-1,sizeof(level));
		head=1;tail=0;level[S]=0;q[++tail]=S;
		for(;head<=tail;head++){
			int node=q[head];
			Auto(i,node)if(e[i].flow>0&&level[e[i].y]==-1){
				level[e[i].y]=level[node]+1;
				q[++tail]=e[i].y;
			}
		}
		return level[T]!=-1;
	}
	int addflow(int node,int flow){
		if(node==T)	return flow;
		int maxflow=0,d=0;
		Auto(i,node)if(level[e[i].y]==level[node]+1&&e[i].flow>0){
			if(d=addflow(e[i].y,min(e[i].flow,flow-maxflow))){
				maxflow+=d;
				e[i].flow-=d;
				e[e[i].reverse].flow+=d;
			}
		}
		if(maxflow==0)level[node]=-1;
		return maxflow;
	}
	void Dinic(int dig){
		int d;
		while(makelevel())
			while(d=addflow(S,oo))
				ans+=(d<<dig);
	}
	void DFS(int node){
		vis[node]=1;tag[node]=1;
		Auto(i,node)if(e[i].flow>0&&!vis[e[i].y])
			DFS(e[i].y);
	}
	void Solve(){
		up(dig,0,31){
			up(i,1,N){
				if(used[i])	tag[i]=((Val[i]&(1<<dig))>>dig);
				else 		tag[i]=-1;
			}
			Build();
			Dinic(dig);
			up(i,1,N)tag[i]=0;
			memset(vis,0,sizeof(vis));
			DFS(S);
			up(i,1,N)if(!used[i])Val[i]|=(tag[i]<<dig);
		}
		up(i,1,N)printf("%d\n",Val[i]);
	}
}
int main(){
	//freopen("input.in","r",stdin);
	using namespace solution;
	TT=read();
	while(TT--){
		Prepare();
		Solve();
	}
	return 0;
}

SPOJ839 OPTM - Optimal Marks的更多相关文章

  1. 图论(网络流):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 ...

  2. SPOJ OPTM - Optimal Marks

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

  3. 【SPOJ839】Optimal Marks 网络流

    You are given an undirected graph G(V, E). Each vertex has a mark which is an integer from the range ...

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

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

  5. spoj 839 OPTM - Optimal Marks&&bzoj 2400【最小割】

    因为是异或运算,所以考虑对每一位操作.对于所有已知mark的点,mark的当前位为1则连接(s,i,inf),否则连(i,t,inf),然后其他的边按照原图连(u,v,1),(v,u,1),跑最大流求 ...

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

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

  7. [SPOJ839]Optimal Marks

    [SPOJ839]Optimal Marks 试题描述 You are given an undirected graph \(G(V, E)\). Each vertex has a mark wh ...

  8. SP839 Optimal marks(最小割)

    SP839 Optimal marks(最小割) 给你一个无向图G(V,E). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记.对于边(u,v),我们定义Cost(u,v)= ...

  9. Optimal Marks(optimal)

    Optimal Marks(optimal) 题目描述 定义无向图边的值为这条边连接的两个点的点权异或值. 定义无向图的值为无向图中所有边的值的和. 给定nn个点mm条边构成的图.其中有些点的权值是给 ...

随机推荐

  1. PHP显示超全局变量和显示程序执行时间

    <?php header('Content-type: text/html; charset=utf-8'); $t1 = microtime(true);//记录脚本刚开始运行是的时间戳 ec ...

  2. AI 人工智能 探索 (四)

    在写之前,先对昨天寻路插件再做一些补充,因为该插件不是很完善,所以当我发现有不能满足需求的时候,就会试图更改源代码,或增加接口来符合我的需求. 昨天补充了一条是 自身转向代码,今天补充另外一条,是及时 ...

  3. PAT1002

    This time, you are supposed to find A+B where A and B are two polynomials. 这一次,你被要求计算A+B当A和B是两个多项式的时 ...

  4. System.Web.Optimization找不到引用怎么办?

    Install-Package Microsoft.AspNet.Web.Optimization

  5. CSS代码格式化工具

    CSS代码格式化工具 http://tool.lanrentuku.com/cssformat/ 可实现CSS代码格式化和CSS在线压缩 请将CSS代码复制到下面表单中:    

  6. vsftp访问异常

    在LINUX下vsftp建立一个FTP服务器,但通过ftp的命令控制台使用FTP时,ls无法查看目录, 当然更无法上传下载文件了! 出错如下 : ftp> ls 227 Entering Pas ...

  7. CGAffineTransform 放射变换解析 即矩阵变换

    转载自;http://www.cocoachina.com/bbs/3g/read.php?tid=151136 矩阵乘法A B相乘要A的列数等于B的行数才有定义,结果是一个 A行B列的矩阵C,C的每 ...

  8. HDU 1527 取石子游戏(威佐夫博弈)

    基础威佐夫博弈,判断奇异局势即可,判断方式为k为两数之差绝对值,(sqrt(5) + 1) / 2 * k若等于两数小者则为奇异局势,也就是必败态. #include<stdio.h> # ...

  9. Robot Framework用法总结

    今天总结下Robot Framework最基本的用法,一来呢,希望自己以后看到这篇总结,很快能回忆起如何使用Robot Framework.二来呢,以初学者的姿态总结Robot Framework,希 ...

  10. 转:XPath路径表达式

    XPath 使用路径表达式来选取 XML 文档中的节点或节点集.节点是通过沿着路径 (path) 或者步 (steps) 来选取的. XML 实例文档 我们将在下面的例子中使用这个 XML 文档. & ...