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 }

 

 

你可能感兴趣的:(poj)