Ural 1099 Work Scheduling (一般图的最大匹配:带花树算法)

http://acm.timus.ru/problem.aspx?space=1&num=1099

贴板题,找一般图的最大匹配数,并输出最大匹配

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<string>
  6 #include<cmath>
  7 #include<set>
  8 #include<list>
  9 #include<map>
 10 #include<iterator>
 11 #include<cstdlib>
 12 #include<vector>
 13 #include<queue>
 14 #include<stack>
 15 #include<algorithm>
 16 #include<functional>
 17 using namespace std;
 18 typedef long long LL;
 19 #define ROUND(x) round(x)
 20 #define FLOOR(x) floor(x)
 21 #define CEIL(x) ceil(x)
 22 //const int maxn=0;
 23 const int inf=0x3f3f3f3f;
 24 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
 25 const double INF=1e30;
 26 const double eps=1e-6;
 27 
 28 /**
 29 *一般图的最大基数匹配:带花树算法
 30 *输入:g[][],n(输入从0到n-1,用addEdge()加边)
 31 *输出:gao()(最大匹配数),match[](匹配)
 32 */
 33 const int maxn=250;
 34 struct Matching
 35 {
 36     deque<int> Q;
 37     int n;
 38     //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点
 39     bool g[maxn][maxn],inque[maxn],inblossom[maxn],inpath[maxn];
 40     int match[maxn],pre[maxn],base[maxn];
 41 
 42     //找公共祖先
 43     int findancestor(int u,int v)
 44     {
 45         memset(inpath,0,sizeof(inpath));
 46         while(1)
 47         {
 48             u=base[u];
 49             inpath[u]=true;
 50             if(match[u]==-1)break;
 51             u=pre[match[u]];
 52         }
 53         while(1)
 54         {
 55             v=base[v];
 56             if(inpath[v])return v;
 57             v=pre[match[v]];
 58         }
 59     }
 60 
 61     //压缩花
 62     void reset(int u,int anc)
 63     {
 64         while(u!=anc)
 65         {
 66             int v=match[u];
 67             inblossom[base[u]]=1;
 68             inblossom[base[v]]=1;
 69             v=pre[v];
 70             if(base[v]!=anc)pre[v]=match[u];
 71             u=v;
 72         }
 73     }
 74 
 75     void contract(int u,int v,int n)
 76     {
 77         int anc=findancestor(u,v);
 78         //SET(inblossom,0);
 79         memset(inblossom,0,sizeof(inblossom));
 80         reset(u,anc);
 81         reset(v,anc);
 82         if(base[u]!=anc)pre[u]=v;
 83         if(base[v]!=anc)pre[v]=u;
 84         for(int i=1; i<=n; i++)
 85             if(inblossom[base[i]])
 86             {
 87                 base[i]=anc;
 88                 if(!inque[i])
 89                 {
 90                     Q.push_back(i);
 91                     inque[i]=1;
 92                 }
 93             }
 94     }
 95 
 96     bool dfs(int S,int n)
 97     {
 98         for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i;
 99         Q.clear();
100         Q.push_back(S);
101         inque[S]=1;
102         while(!Q.empty())
103         {
104             int u=Q.front();
105             Q.pop_front();
106             for(int v=1; v<=n; v++)
107             {
108                 if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
109                 {
110                     if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
111                     else if(pre[v]==-1)
112                     {
113                         pre[v]=u;
114                         if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
115                         else
116                         {
117                             u=v;
118                             while(u!=-1)
119                             {
120                                 v=pre[u];
121                                 int w=match[v];
122                                 match[u]=v;
123                                 match[v]=u;
124                                 u=w;
125                             }
126                             return true;
127                         }
128                     }
129                 }
130             }
131         }
132         return false;
133     }
134 
135     void init(int n)
136     {
137         this->n = n;
138         memset(match,-1,sizeof(match));
139         memset(g,0,sizeof(g));
140     }
141 
142     void addEdge(int a, int b)
143     {
144         ++a;
145         ++b;
146         g[a][b] = g[b][a] = 1;
147     }
148 
149     int gao()
150     {
151         int ans = 0;
152         for (int i = 1; i <= n; ++i)
153             if (match[i] == -1 && dfs(i, n))
154                 ++ans;
155         return ans;
156     }
157 } match;
158 
159 int n,m;
160 void input()
161 {
162     scanf("%d",&n);
163     match.init(n);
164     int u,v;
165     while(~scanf("%d%d",&u,&v)) match.addEdge(--u,--v);
166 }
167 void solve()
168 {
169     int ans=match.gao();
170     printf("%d\n",2*ans);
171     int out[maxn];
172     memset(out,-1,sizeof(out));
173     for(int i=1;i<=n;i++)
174     {
175         if(match.match[i]!=-1)
176         {
177             if(out[i]==match.match[i]||out[match.match[i]]==i) continue;
178             out[i]=match.match[i];
179         }
180     }
181     for(int i=1;i<=n;i++)
182     {
183         if(out[i]!=-1) printf("%d %d\n",i,out[i]);
184     }
185 }
186 int main()
187 {
188     std::ios_base::sync_with_stdio(false);
189 //    freopen("in.cpp","r",stdin);
190     input();
191     solve();
192     return 0;
193 }
View Code

 

posted @ 2013-08-21 13:56  xysmlx  阅读(336)  评论(0编辑  收藏  举报