SPOJ Optimal Marks
https://vjudge.net/problem/SPOJ-OPTM
每位分别考虑后,相当于给所有点分两类,不同类之间的边会产生花费。即求最小割,源点向所有已知的这位为0的点连无穷边,所有已知的这位为1的点向汇点连无穷边。为了使总和尽量小,跑完最小割后,从汇点开始dfs找出残留网络种能到达汇点的点,置为1,除它们外的所有点都置为0。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6 #define LL long long 7 8 int n,m,numofmk,T; 9 #define maxn 511 10 #define maxm 3011*4+maxn*2 11 int mk[maxn],ans[maxn]; 12 13 struct Edge{int to,next,cap,flow;}; 14 struct Net 15 { 16 int n,le,s,t,first[maxn],dis[maxn],cur[maxn],que[maxn],head,tail; Edge edge[maxm]; bool vis[maxn]; 17 void clear(int N) {n=N; le=2; memset(first,0,sizeof(first)); memset(vis,0,sizeof(vis));} 18 void in(int x,int y,int c) {Edge &e=edge[le]; e.to=y; e.cap=c; e.flow=0; e.next=first[x]; first[x]=le++;} 19 void insert(int x,int y,int c) {in(x,y,c); in(y,x,0);} 20 bool bfs() 21 { 22 memset(dis,0,sizeof(dis)); 23 head=0; tail=1; que[0]=s; dis[s]=1; 24 while (head!=tail) 25 { 26 int x=que[head++]; 27 for (int i=first[x];i;i=edge[i].next) 28 { 29 Edge &e=edge[i]; if (dis[e.to] || e.cap==e.flow) continue; 30 dis[e.to]=dis[x]+1; que[tail++]=e.to; 31 } 32 } 33 return dis[t]>0; 34 } 35 int dfs(int x,int a) 36 { 37 if (x==t || !a) return a; 38 int flow=0,f; 39 for (int &i=cur[x];i;i=edge[i].next) 40 { 41 Edge &e=edge[i]; 42 if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0) 43 { 44 e.flow+=f; 45 flow+=f; 46 edge[i^1].flow-=f; 47 a-=f; 48 if (!a) break; 49 } 50 } 51 return flow; 52 } 53 int Dinic(int S,int T) 54 { 55 s=S; t=T; 56 int flow=0; 57 while (bfs()) 58 { 59 for (int i=1;i<=n;i++) cur[i]=first[i]; 60 flow+=dfs(s,0x3f3f3f3f); 61 } 62 return flow; 63 } 64 void dfs2(int x) 65 { 66 vis[x]=1; 67 for (int i=first[x];i;i=edge[i].next) 68 if (edge[i^1].cap>edge[i^1].flow && !vis[edge[i].to]) dfs2(edge[i].to); 69 } 70 }g,g2; 71 72 int main() 73 { 74 scanf("%d",&T); 75 while (T--) 76 { 77 scanf("%d%d",&n,&m); 78 g.clear(n+2); 79 for (int i=1,x,y;i<=m;i++) 80 { 81 scanf("%d%d",&x,&y); 82 g.insert(x,y,1); g.insert(y,x,1); 83 } 84 memset(mk,-1,sizeof(mk)); 85 memset(ans,0,sizeof(ans)); 86 scanf("%d",&numofmk); 87 for (int i=1,x;i<=numofmk;i++) 88 { 89 scanf("%d",&x); 90 scanf("%d",&mk[x]); 91 ans[x]=mk[x]; 92 } 93 94 for (int i=0;i<=30;i++) 95 { 96 g2=g; 97 for (int j=1;j<=n;j++) if (mk[j]!=-1) 98 { 99 if ((mk[j]>>i)&1) g2.insert(j,n+2,0x3f3f3f3f); 100 else g2.insert(n+1,j,0x3f3f3f3f); 101 } 102 g2.Dinic(n+1,n+2); 103 memset(g2.vis,0,sizeof(g2.vis)); 104 g2.dfs2(n+2); 105 for (int j=1;j<=n;j++) ans[j]|=(g2.vis[j]<<i); 106 } 107 for (int i=1;i<=n;i++) printf("%d\n",ans[i]); 108 } 109 return 0; 110 }