题意:给出一个无向图, 图中的一些点有mark值, 每条边<u,v>的权值为mark[u]^mark[v], 现在给出了一些点的mark值,现在想让你求出其他点的mark值让边权和最小。 点的个数100, 边的的个数为3000
思路: 对于mark值不同位的值是不影响的,所以可以一位一位的处理。对于每一位只能是1和0,对不不知道的点的mark只能是1和0,所以最后的问题就是将这些点分到两个集合中。 两个点之间如果不是一个集合并且还有边的话那么答案就要花费1. 我们这样建图。
对于当前位mark值为1的点建一个<s,u, INF>的边, 对于为0的点我们建立<u,t,INF>的边。 对于普通的边建立一个
<u,v,1>,<v,u,1>的边。 让割最小就行。这样就转化成了最大刘德问题。
AC代码:
View Code
1 #include <cstdio>
2 #include <cstring>
3 #include <queue>
4 #include <string>
5 #include <iostream>
6 using namespace std;
7 const int N = 600, M = 30010, INF=1<<29;
8 struct EDGE
9 {
10 int u, v, cap, next;
11 }edge[M], p[M];
12
13 int num, head[N], mark[N], ans[N];
14 int gap[N], dis[N], pre[N], cur[N];
15 int n, m;
16 bool used[N];
17
18 void init()
19 {
20 int u, w, k;
21 scanf("%d%d", &n, &m);
22 for(int i=0; i<m; i++)
23 {
24 scanf("%d%d", &p[i].u, &p[i].v);
25 }
26 memset(mark, -1, sizeof(mark));
27 memset(ans, 0, sizeof(ans));
28 scanf("%d", &k);
29 while(k--)
30 {
31 scanf("%d%d", &u, &w);
32 mark[u] = w;
33 }
34 }
35
36 void add(int u, int v, int w)
37 {
38 edge[num].u = u;
39 edge[num].v = v;
40 edge[num].cap = w;
41 edge[num].next = head[u];
42 head[u] = num++;
43 }
44
45 void build(int k)
46 {
47 for(int i=1; i<=n; i++)
48 {
49 if(mark[i] != -1)
50 {
51 if(mark[i]&(1<<k))
52 {
53 add(0, i, INF);
54 add(i, 0, 0);
55 }
56 else
57 {
58 add(i, n+1, INF);
59 add(n+1, i, 0);
60 }
61 }
62 }
63 for(int i=0; i<m; i++)
64 {
65 add(p[i].u, p[i].v, 1);
66 add(p[i].v, p[i].u, 0);
67 add(p[i].v, p[i].u, 1);
68 add(p[i].u, p[i].v, 0);
69 }
70 }
71
72 int SAP(int s,int t) //sap模版
73 {
74 memset(gap,0,sizeof(gap));
75 memset(dis,0,sizeof(dis));
76 int i;
77 for(i=0; i<=t;i++)
78 {
79 cur[i] = head[i];
80 }
81 int top=s;
82 gap[s]=t+1;
83 long long maxflow=0,flow=M;
84 while(dis[s] < t+1)
85 {
86 for(i=cur[top];i != -1;i = edge[i].next)
87 {
88 if(edge[i].cap > 0 && dis[top] == dis[edge[i].v] + 1)
89 break;
90 }
91 if(i != -1)
92 {
93 cur[top] = i;
94 int v = edge[i].v;
95 if(edge[i].cap < flow)
96 {
97 flow = edge[i].cap;
98 }
99 top = v;
100 pre[v] = i;
101 if(top == t)
102 {
103 maxflow += flow;
104 while(top != s)
105 {
106 edge[pre[top]].cap -= flow;
107 edge[pre[top]^1].cap += flow;
108 top = edge[pre[top]^1].v;
109 }
110 flow = M;
111 }
112 }
113 else
114 {
115 if(--gap[dis[top]] == 0)
116 {
117 break;
118 }
119 dis[top] = t+1;
120 cur[top] = head[top];
121 for(int j=head[top];j != -1;j=edge[j].next)
122 {
123 if(edge[j].cap > 0 && dis[edge[j].v] + 1 < dis[top])
124 {
125 dis[top] = dis[edge[j].v] + 1;
126 cur[top] = j;
127 }
128 }
129 gap[dis[top]]++;
130 if(top != s)
131 {
132 top = edge[pre[top]^1].v;
133 }
134 }
135 }
136 return maxflow;
137 }
138
139 void dfs(int u, int k)
140 {
141 int v;
142 if(u>=1 && u<=n)
143 {
144 ans[u] |= (1<<k);
145 }
146 used[u] = 1;
147 for(int i=head[u]; i!=-1; i=edge[i].next)
148 {
149 if(edge[i].cap>0 && !used[edge[i].v])
150 {
151 dfs(edge[i].v, k);
152 }
153 }
154 }
155
156 void solve()
157 {
158 for(int i=0; i<32; i++)
159 {
160 num = 0;
161 memset(head, -1, sizeof(head));
162
163 build(i);
164 SAP(0,n+1);
165 memset(used, 0, sizeof(used));
166 dfs(0,i);
167 }
168 for(int i=1; i<=n; i++)
169 {
170 printf("%d\n", ans[i]);
171 }
172 }
173
174 int main()
175 {
176 int t;
177 scanf("%d", &t);
178 while(t--)
179 {
180 init();
181 solve();
182 }
183 return 0;
184 }
来源:https://www.cnblogs.com/gufeiyang/archive/2012/10/08/2715257.html
