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 }
来源:https://www.cnblogs.com/Blue233333/p/12262498.html
