考驗代碼能力的題目,感覺網絡流一要求輸出方案我就寫的醜
因為如果一個點染色确定後,整個圖的染色也就确定了;
對于兩個點u和v, 令它們之間的最短路是dis(u,v), 那麼交換它們兩個顔色的最少步數是dis(u,v), 且存在一種交換序列不會破壞其它節點的顔色
這是兩個突破口
我的一個WA的地方在于:構造方案時沒有把路徑上的顔色交換……
1 #include<bits/stdc++.h>
2 #define mp make_pair
3 #define pi pair<int,int>
4 using namespace std;
5 const int inf=1e9+7;
6 struct node{int po,next,flow,cost;} e[2000010];
7 pi a[100010];
8 vector<pi> tmp;
9 vector<int> g[510],s[2];
10 int f[510][510],from[510][510],q[1000010],pre[510],cur[510],d[510],p[510],mark[510],cl[510],rc[510];
11 bool v[510];
12 int n,m,len,t,ans,s1,s0;
13 void add(int x,int y,int f,int c)
14 {
15 e[++len].po=y;
16 e[len].flow=f;
17 e[len].cost=c;
18 e[len].next=p[x];
19 p[x]=len;
20 }
21
22 void build(int x,int y, int f, int c)
23 {
24 add(x,y,f,c);
25 add(y,x,0,-c);
26 }
27
28 bool spfa()
29 {
30 int f=1,r=1;
31 for (int i=1; i<=t; i++) d[i]=inf;
32 memset(v,0,sizeof(v));
33 d[0]=0; q[1]=0;
34 while (f<=r)
35 {
36 int x=q[f++];
37 v[x]=0;
38 for (int i=p[x]; i!=-1; i=e[i].next)
39 {
40 int y=e[i].po;
41 if (e[i].flow&&d[x]+e[i].cost<d[y])
42 {
43 d[y]=d[x]+e[i].cost;
44 pre[y]=x; cur[y]=i;
45 if (!v[y])
46 {
47 q[++r]=y;
48 v[y]=1;
49 }
50 }
51 }
52 }
53 return d[t]<inf;
54 }
55
56 int mincost()
57 {
58 int s=0;
59 while (spfa())
60 {
61 s+=d[t];
62 for (int i=t; i; i=pre[i])
63 {
64 int j=cur[i];
65 e[j].flow--;
66 e[j^1].flow++;
67 }
68 }
69 return s;
70 }
71
72 void bfs(int st)
73 {
74 memset(v,0,sizeof(v));
75 for (int i=1; i<=n; i++) f[st][i]=inf;
76 int h=1,r=1; q[1]=st; v[st]=0; f[st][st]=0;
77 while (h<=r)
78 {
79 int x=q[h++];
80 for (int i=0; i<g[x].size(); i++)
81 {
82 int y=g[x][i];
83 if (!v[y])
84 {
85 f[st][y]=f[st][x]+1;
86 from[st][y]=x;
87 v[y]=1;
88 q[++r]=y;
89 }
90 }
91 }
92 }
93
94 bool get(int x,int w)
95 {
96 mark[x]=w; s[w].push_back(x);
97 if (rc[x]==1) s1++; else s0++;
98 for (int i=0; i<g[x].size(); i++)
99 {
100 int y=g[x][i];
101 if (mark[y]==-1) get(y,w^1);
102 else if (mark[y]==mark[x]) return 0;
103 }
104 return 1;
105 }
106
107 void path(int st,int en,int w)
108 {
109 int x=en,r=1; q[1]=en;
110 while (x!=st)
111 {
112 x=from[st][x];
113 q[++r]=x;
114 if (cl[x]^cl[q[1]])
115 {
116 for (int i=r; i>1; i--)
117 {
118 tmp.push_back(mp(q[i],q[i-1]));
119 swap(cl[q[i]],cl[q[i-1]]);
120 }
121 r=1; q[1]=x;
122 }
123 }
124 }
125
126 void way(int w)
127 {
128 for (int i=1; i<=n; i++) cl[i]=rc[i];
129 for (int i=0; i<=len; i+=2)
130 {
131 int y=e[i].po,x=e[i^1].po;
132 if (x&&y<t&&e[i].flow==0) path(x,y,w);
133 }
134 }
135
136 void graph(int w)
137 {
138 len=-1; memset(p,255,sizeof(p));
139 for (int i=0; i<s[0].size(); i++)
140 {
141 int x=s[0][i];
142 if (rc[x]^w) build(0,x,1,0);
143 }
144 for (int i=0; i<s[1].size(); i++)
145 {
146 int x=s[1][i];
147 if (rc[x]^w) continue;
148 build(x,t,1,0);
149 for (int j=0; j<s[0].size(); j++)
150 {
151 int y=s[0][j];
152 if (rc[y]^w) build(y,x,1,f[y][x]);
153 }
154 }
155 }
156
157 bool check(int x)
158 {
159 s1=s0=0;
160 s[0].clear(); s[1].clear();
161 if (!get(x,0)) return 0;
162 if (s1+s0==1) return 1;
163 if (s0!=s[0].size()&&s0!=s[1].size()) return 0;
164 int ans1=inf,ans2=inf;
165 if (s0==s[0].size())
166 {
167 graph(0); ans1=mincost();
168 tmp.clear(); way(0);
169 }
170 if (s1==s[0].size())
171 {
172 graph(1);
173 ans2=mincost();
174 }
175 if (ans1==inf&&ans2==inf) return 0;
176 if (ans2<ans1)
177 {
178 tmp.clear(); way(1);
179 for (int i=0; i<tmp.size(); i++)
180 a[++ans]=tmp[i];
181 }
182 else {
183 for (int i=0; i<tmp.size(); i++)
184 a[++ans]=tmp[i];
185 }
186 return 1;
187 }
188
189 int main()
190 {
191 int cas;
192 scanf("%d",&cas);
193 while (cas--)
194 {
195 scanf("%d%d\n",&n,&m);
196 for (int i=1; i<=n; i++) g[i].clear();
197 for (int i=1; i<=n; i++)
198 {
199 char ch=getchar();
200 rc[i]=ch-'0';
201 }
202 for (int i=1; i<=m; i++)
203 {
204 int x,y;
205 scanf("%d%d",&x,&y);
206 g[x].push_back(y);
207 g[y].push_back(x);
208 }
209 for (int i=1; i<=n; i++) bfs(i);
210 memset(mark,255,sizeof(mark));
211 bool ff=1; ans=0; t=n+1;
212 for (int i=1; i<=n; i++)
213 if (mark[i]==-1)
214 {
215 ff&=check(i);
216 if (!ff) break;
217 }
218
219 if (!ff) puts("-1");
220 else {
221 printf("%d\n",ans);
222 for (int i=1; i<=ans; i++)
223 printf("%d %d\n",a[i].first,a[i].second);
224 }
225 }
226 }