[Cogs728] [网络流24题#3] 最小路径覆盖 [网络流,最大流,二分图匹配]

建图:源点—>边的起点(集合1中的)—>边的终点(集合2中的)—>汇点,所有边权均为1,

计算最大流,最后枚举起点的出边,边权为0的即为匹配上的,

可以这样理解:每条边表示起点和终点形成一组可选匹配,所以每个点只能被匹配1次(做起点和终点分别1次),所以可以看成是二分图匹配。

代码略丑:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <algorithm>
  8 #include <queue>
  9 
 10 using namespace std;
 11 
 12 template<const int _n>
 13 struct    Edge
 14 {
 15     struct Edge_base { int    to,next,w; }e[_n];
 16     int    cnt,p[_n];
 17     Edge() { clear(); }
 18     int    start(const int x) { return p[x]; }
 19     void    insert(const int x,const int y,const int z)
 20     { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; p[x]=cnt; return ; }
 21     Edge_base&    operator[](const int x) { return e[x]; }
 22     void    clear() { cnt=1,memset(p,0,sizeof(p)); }
 23 };
 24 
 25 int    n,m,SSS,TTT,Ans;
 26 int    level[310],cur[310],Out[310],to[310],from[310];
 27 bool    visited[310];
 28 Edge<15000>    e;
 29 
 30 bool    Bfs(const int S)
 31 {
 32     int    i,t;
 33     queue<int>    Q;
 34     memset(level,0,sizeof(level));
 35     level[S]=1;
 36     Q.push(S);
 37     while(!Q.empty())
 38     {
 39         t=Q.front();Q.pop();
 40         for(i=e.start(t);i;i=e[i].next)
 41         {
 42             if(!level[e[i].to] && e[i].w)
 43             {
 44                 level[e[i].to]=level[t]+1;
 45                 Q.push(e[i].to);
 46             }
 47         }
 48     }
 49     return level[TTT];
 50 }
 51 
 52 int    Dfs(const int S,const int bk)
 53 {
 54     if(S==TTT)return bk;
 55     int    rest=bk;
 56     for(int &i=cur[S];i;i=e[i].next)
 57     {
 58         if(level[e[i].to]==level[S]+1 && e[i].w)
 59         {
 60             int    flow=Dfs(e[i].to,min(e[i].w,rest));
 61             e[i].w-=flow;
 62             e[i^1].w+=flow;
 63             if((rest-=flow)<=0)break;
 64         }
 65     }
 66     if(bk==rest)level[S]=0;
 67     return bk-rest;
 68 }
 69 
 70 int    Dinic()
 71 {
 72     int    flow=0;
 73     while(Bfs(SSS))
 74     {
 75         memcpy(cur,e.p,sizeof(int)*(n+n+3));
 76         flow+=Dfs(SSS,0x3f3f3f3f);
 77     }
 78     return flow;
 79 }
 80 
 81 
 82 
 83 int main()
 84 {
 85     freopen("path3.in","r",stdin);
 86     freopen("path3.out","w",stdout);
 87     int    i,j,x,y;
 88 
 89     scanf("%d%d",&n,&m);
 90     for(i=1;i<=m;++i)
 91     {
 92         scanf("%d%d",&x,&y);
 93         e.insert(x,y+n,1);
 94         e.insert(y+n,x,0);
 95         Out[x]++;
 96     }
 97 
 98     SSS=n+n+1,TTT=n+n+2;
 99     for(i=1;i<=n;++i)
100     {
101         e.insert(SSS,i,1);
102         e.insert(i,SSS,0);
103         e.insert(i+n,TTT,1);
104         e.insert(TTT,i+n,0);
105     }
106 
107     Dinic();
108 
109     for(i=e.start(SSS);i;i=e[i].next)
110     {
111         if(e[i].w)continue;
112         for(j=e.start(e[i].to);j;j=e[j].next)
113         {
114             if(e[j].to!=SSS && !e[j].w)
115             {
116                 to[e[i].to]=e[j].to-n;
117                 from[e[j].to-n]=e[i].to;
118                 break;
119             }
120         }
121     }
122 
123     for(i=1;i<=n;++i)
124     {
125         if(!from[i])
126         {
127             int t=i;
128             while(t)
129             {
130                 printf("%d ",t);
131                 t=to[t];
132             }
133             printf("\n");
134             Ans++;
135         }
136     }
137 
138     printf("%d\n",Ans);
139 
140     return 0;
141 }
View Code

匈牙利写法详见:http://www.cnblogs.com/Ngshily/p/4988909.html

posted @ 2015-11-23 18:46  Gster  阅读(148)  评论(0编辑  收藏  举报