SPOJ 839 最小割

题意:

给出一些权已知的点(剩下的点的权未知),以及所有点之间的边的关系,每条边的权是其两端点的点权值的异或值,求未知点的权是什么的时候所有边权的和最小

题解:

amber的论文题,简直太绝了!

http://kanboxshare.com/link/v0yHI2oUoSNMCo8mAmj1Bxy0mqMIH6tZNUsbGxG4mvu3FNl9FfiODWiEmdvTHKBRNUbpNxELmvNwA2rCFwu1DeAXb0I7HoBFNmIvNVIXmNYmFNl43dPYfIaGnVeFDB5XszPnT5jttcdCQ

思想就是按位做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 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2852009.html