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

题意:

给定N个环卫,和若干匹配关系。求最大匹配,并输出解。

思路:

【一般图最大匹配】裸

 

注意:该题只有一组测试数据,匹配关系(边)输入到EOF.

 

  1 /*
  2 ural 1099
  3 一般图最大匹配:带花树算法(模板)
  4 g[][]储存边
  5 复杂度:N^3
  6 solve(n),求解,返回匹配数
  7 match[],匹配的解
  8 */
  9 #include<stdio.h>
 10 #include<string.h>
 11 #include<math.h>
 12 #include<algorithm>
 13 #include<queue>
 14 
 15 using namespace std;
 16 
 17 #define MAXE 250*250
 18 #define MAXN 250
 19 
 20 deque<int> Q;
 21 bool g[MAXN][MAXN];
 22 bool inque[MAXN];
 23 bool inblossom[MAXN];
 24 int match[MAXN];
 25 int pre[MAXN];
 26 int base[MAXN];
 27 
 28 //找公共祖先
 29 int findancestor(int u ,int v)
 30 {
 31     bool inpath[MAXN] = {false};
 32     while (1)
 33     {
 34         u = base[u];
 35         inpath[u] = true;
 36         if (match[u] == -1)
 37             break;
 38         u = pre[match[u]];
 39     }
 40     while (1)
 41     {
 42         v = base[v];
 43         if (inpath[v])
 44             return v;
 45         v = pre[match[v]];
 46     }
 47 }
 48 
 49 void reset(int u,int anc)
 50 {
 51     while (u != anc)
 52     {
 53         int v = match[u];
 54         inblossom[base[u]] = 1;
 55         inblossom[base[v]] = 1;
 56         v = pre[v];
 57         if (base[v] != anc)
 58             pre[v] = match[u];
 59         u = v;
 60     }
 61 }
 62 
 63 void contract(int u,int v,int n)
 64 {
 65     int anc = findancestor(u,v);
 66     memset(inblossom,0,sizeof(inblossom));
 67 
 68     reset(u,anc);
 69     reset(v,anc);
 70 
 71     if (base[u]!=anc)
 72         pre[u] = v;
 73     if (base[v]!=anc)
 74         pre[v] = u;
 75     for (int i=1; i<=n; i++)
 76     {
 77         if (inblossom[base[i]])
 78         {
 79             base[i] = anc;
 80             if (!inque[i])
 81             {
 82                 Q.push_back(i);
 83                 inque[i] = 1;
 84             }
 85         }
 86     }
 87 }
 88 
 89 bool dfs(int S,int n)
 90 {
 91     for (int i=0; i<=n; i++)
 92     {
 93         pre[i] = -1;
 94         inque[i] = 0;
 95         base[i] = i;
 96     }
 97 
 98     Q.clear();
 99     Q.push_back(S);
100     inque[S] = 1;
101 
102     while (!Q.empty())
103     {
104         int u = Q.front();
105         Q.pop_front();
106 
107         for (int v = 1; v<=n; v++)
108         {
109             if (g[u][v] && base[v]!=base[u] && match[u]!=v)
110             {
111                 if(v == S || (match[v]!=-1 && pre[match[v]]!=-1))
112                 {
113                     contract(u,v,n);
114                 }
115                 else if (pre[v]==-1)
116                 {
117                     pre[v] = u;
118                     if (match[v]!=-1)
119                     {
120                         Q.push_back(match[v]);
121                         inque[match[v]] = 1;
122                     }
123                     else
124                     {
125                         u = v;
126                         while (u!=-1)
127                         {
128                             v = pre[u];
129                             int w = match[v];
130                             match[u] = v;
131                             match[v] = u;
132                             u = w;
133                         }
134                         return true;
135                     }
136                 }
137             }
138         }
139     }
140     return false;
141 }
142 int solve(int n)
143 {
144     memset(match,-1,sizeof(match));
145     int ans = 0;
146     for (int i=1; i<=n; i++)
147     {
148         if (match[i]==-1 && dfs(i,n))
149         {
150             ans++;
151         }
152     }
153     return ans;
154 }
155 
156 int n;
157 int main()
158 {
159     memset(g,0,sizeof(g));
160     scanf("%d",&n);
161     int u ,v;
162     while (scanf("%d%d",&u,&v)==2)
163     {
164         g[u][v] = g[v][u] = 1;
165     }
166     int ans = solve(n);
167     printf("%d\n",2*ans);
168     for (int i=1; i<=n; i++)
169     {
170         if (match[i]!=-1)
171         {
172             printf("%d %d\n",i,match[i]);
173             match[match[i]] = -1;
174             match[i] = -1;
175         }
176     }
177     return 0;
178 }
ural1099(一般图最大匹配)

 

转载于:https://www.cnblogs.com/wangsouc/articles/3274373.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值