考验代码能力的题目,感觉网络流一要求输出方案我就写的丑

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",&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 }
View Code

 

posted on 2017-02-26 21:43  acphile  阅读(279)  评论(0编辑  收藏  举报