题目链接
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17875
题目大意
给定一个
n
个点
思路
最小割。
我们把每个点的点权看成32位的二进制数,这些二进制数,每一位是0还是1都不会影响其他位。因此我们可以将整个题改成:每个点权均为0或1,某些点权已经确定了是0还是1,这样做32次就行了。
可以发现,亦或和为1的只有0 xor 1,比较容易想到最小割。对于每个已经确定点权的点,若该点为1,源向该点连边,否则该点向汇连边。对于原图中每条无向边
u−>v
而言,
u
向
代码
写代码时犯了很多SB的错误。。。我太弱了。。。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXE 10000000
#define MAXV 25000
using namespace std;
int n,m,S,T;
struct edge
{
int u,v,cap,next;
}edges[MAXE];
int head[MAXV],nCount=0;
void AddEdge(int U,int V,int C)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].cap=C;
edges[nCount].next=head[U];
head[U]=nCount;
}
void add(int U,int V,int C)
{
AddEdge(U,V,C);
AddEdge(V,U,0);
}
int q[MAXE],layer[MAXV];
bool CountLayer()
{
memset(layer,-1,sizeof(layer));
int h=0,t=1;
q[h]=S;
layer[S]=1;
while(h<t)
{
int u=q[h++];
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(layer[v]==-1&&edges[p].cap)
{
layer[v]=layer[u]+1;
q[t++]=v;
}
}
}
return layer[T]!=-1;
}
int DFS(int u,int flow)
{
if(u==T) return flow;
int used=0;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(layer[v]==layer[u]+1&&edges[p].cap) //!!!!!!
{
int tmp=DFS(v,min(flow-used,edges[p].cap));
used+=tmp;
edges[p].cap-=tmp;
edges[p^1].cap+=tmp;
if(used==flow) return used;
}
}
if(used==0) layer[u]=-1;
return used;
}
int Dinic()
{
int maxflow=0;
while(CountLayer())
maxflow+=DFS(S,INF);
return maxflow;
}
bool vis[MAXV],map[6000][6000];
int k,mark[6000],id[6000]; //id[i]=第i个已经确定标号的点
void init()
{
nCount=1;
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
}
void DFS2(int u,int digit) //在第digit位下做最小割,检查u是否在S侧
{
vis[u]=true;
mark[u]|=(1<<digit);
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(edges[p].cap&&!vis[v])
DFS2(v,digit); //!!!!!!
}
}
void buildgraph(int digit)
{
for(int i=1;i<=k;i++)
{
if((1<<digit)&mark[id[i]]) add(S,id[i],INF);
else add(id[i],T,INF);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(map[i][j])
add(i,j,1);
}
int main()
{
int TestCase;
scanf("%d",&TestCase);
while(TestCase--)
{
scanf("%d%d",&n,&m);
S=MAXV-2,T=MAXV-1;
memset(mark,0,sizeof(mark));
memset(map,false,sizeof(map));
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
map[u][v]=map[v][u]=true;
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
int x;
scanf("%d",&x);
scanf("%d",&mark[x]);
id[i]=x;
}
for(int i=0;i<=31;i++)
{
init();
buildgraph(i);
Dinic();
DFS2(S,i);
}
for(int i=1;i<=n;i++)
printf("%d\n",mark[i]);
}
return 0;
}