SPOJ 839 最小割
题意:
给出一些权已知的点(剩下的点的权未知),以及所有点之间的边的关系,每条边的权是其两端点的点权值的异或值,求未知点的权是什么的时候所有边权的和最小
题解:
amber的论文题,简直太绝了!
思想就是按位做32遍最小割。
View Code
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 7 #define N 1000 8 #define M 400000 9 #define INF 1e8 10 11 using namespace std; 12 13 int head[N],to[M],next[M],len[M]; 14 int q[M],layer[N],mark[N],pu[M],pv[M],ans[N]; 15 bool vis[N]; 16 int n,m,S,T,cnt,cas; 17 18 inline void add(int u,int v,int w) 19 { 20 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 21 to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++; 22 } 23 24 inline void read() 25 { 26 scanf("%d%d",&n,&m); 27 S=0; T=n+1; 28 for(int i=1;i<=m;i++) scanf("%d%d",&pu[i],&pv[i]); 29 memset(mark,-1,sizeof mark); 30 memset(ans,0,sizeof ans); 31 int tmp; 32 scanf("%d",&tmp); 33 for(int i=1,u,v;i<=tmp;i++) 34 { 35 scanf("%d%d",&u,&v); 36 mark[u]=v; 37 } 38 } 39 40 inline void build(int w) 41 { 42 memset(head,-1,sizeof head); cnt=0; 43 for(int i=1;i<=n;i++) 44 if(mark[i]!=-1) 45 { 46 if(mark[i]&(1<<w)) add(S,i,INF); 47 else add(i,T,INF); 48 } 49 for(int i=1;i<=m;i++) 50 { 51 add(pu[i],pv[i],1); 52 add(pv[i],pu[i],1); 53 } 54 } 55 56 inline bool bfs() 57 { 58 memset(layer,-1,sizeof layer); 59 int h=1,t=2,sta; 60 q[1]=S; layer[S]=0; 61 while(h<t) 62 { 63 sta=q[h++]; 64 for(int i=head[sta];~i;i=next[i]) 65 if(len[i]&&layer[to[i]]<0) 66 { 67 layer[to[i]]=layer[sta]+1; 68 q[t++]=to[i]; 69 } 70 } 71 return layer[T]!=-1; 72 } 73 74 inline int find(int u,int cur_flow) 75 { 76 if(u==T) return cur_flow; 77 int res=0,tmp; 78 for(int i=head[u];~i&&res<cur_flow;i=next[i]) 79 if(len[i]&&layer[to[i]]==layer[u]+1) 80 { 81 tmp=find(to[i],min(cur_flow-res,len[i])); 82 len[i]-=tmp; len[i^1]+=tmp; res+=tmp; 83 } 84 if(!res) layer[u]=-1; 85 return res; 86 } 87 88 inline void dinic() 89 { 90 int ans=0; 91 while(bfs()) ans+=find(S,INF); 92 } 93 94 inline void dfs(int u,int w) 95 { 96 if(u>=1&&u<=n) ans[u]|=(1<<w); 97 vis[u]=true; 98 for(int i=head[u];~i;i=next[i]) 99 if(len[i]>0&&!vis[to[i]]) dfs(to[i],w); 100 } 101 102 inline void go() 103 { 104 for(int i=0;i<32;i++) 105 { 106 build(i); 107 dinic(); 108 memset(vis,0,sizeof vis); 109 dfs(S,i); 110 } 111 for(int i=1;i<=n;i++) printf("%d\n",ans[i]); 112 } 113 114 int main() 115 { 116 scanf("%d",&cas); 117 while(cas--) read(),go(); 118 return 0; 119 }
没有人能阻止我前进的步伐,除了我自己!