考验代码能力的题目,感觉网络流一要求输出方案我就写的丑
http://www.cnblogs.com/duoxiao/p/5777632.html 官方题解写的很详细
因为如果一个点染色确定后,整个图的染色也就确定了;
对于两个点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,&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 ",ans); 222 for (int i=1; i<=ans; i++) 223 printf("%d %d ",a[i].first,a[i].second); 224 } 225 } 226 }