hdu4687Boke and Tsukkomi(无向图匹配的带花树算法 )

题意:

给定一个简单图,询问哪些边如果选择的话会使得剩下的图中最大的匹配数减少。

 

思路:

先求出最大匹配数,然后枚举每一条边,再做最大匹配看是否为最大匹配数.求无向图的最大匹配数,带花树算法。模板,等待学习中>

http://fanhq666.blog.163.com/blog/static/8194342620120304463580/

这里说得很详细

 

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <queue>
  4 #include <string.h>
  5 #define SET(a,b) memset(a,b,sizeof(a));
  6 using namespace std;
  7 
  8 const int MAX=44;
  9 queue<int> Q;
 10 int g[MAX][MAX],inque[MAX],inblossom[MAX];
 11 int match[MAX],pre[MAX],set[MAX];
 12 int n;
 13 
 14 int mat[MAX][MAX];
 15 
 16 int findancestor(int u,int v)
 17 {
 18     int visit[MAX]={0};
 19     while(1)
 20     {
 21         u=set[u];
 22         visit[u]=1;
 23         if(match[u]==-1) break;
 24         u=pre[match[u]];
 25     }
 26     while(1)
 27     {
 28         v=set[v];
 29         if(visit[v]) break;
 30         v=pre[match[v]];
 31     }
 32     return v;
 33 }
 34 
 35 
 36 void reset(int u,int root)
 37 {
 38     int v;
 39     while(u!=root)
 40     {
 41         v=match[u];
 42         inblossom[set[u]]=1;
 43         inblossom[set[v]]=1;
 44         v=pre[v];
 45         if(set[v]!=root) pre[v]=match[u];
 46         u=v;
 47     }
 48 }
 49 
 50 void contract(int u,int v)
 51 {
 52     int root=findancestor(u,v);
 53     int i;
 54     SET(inblossom,0);
 55     reset(u,root);
 56     reset(v,root);
 57     if(set[u]!=root) pre[u]=v;
 58     if(set[v]!=root) pre[v]=u;
 59     for(i=1;i<=n;i++) if(inblossom[set[i]])
 60     {
 61         set[i]=root;
 62         if(!inque[i]) Q.push(i),inque[i]=1;
 63     }
 64 }
 65 
 66 int BFS(int S)
 67 {
 68     int u,v,i,t;
 69     for(i=1;i<=n;i++)pre[i]=-1,inque[i]=0,set[i]=i;
 70     while(!Q.empty()) Q.pop();
 71     Q.push(S);
 72     inque[S]=1;
 73     while(!Q.empty())
 74     {
 75         u=Q.front();
 76         Q.pop();
 77         for(v=1;v<=n;v++)if(g[u][v]&&set[v]!=set[u]&&match[u]!=v)
 78         {
 79             if(v==S||match[v]!=-1&&pre[match[v]]!=-1) contract(u,v);
 80             else if(pre[v]==-1)
 81             {
 82                 pre[v]=u;
 83                 if(match[v]!=-1)
 84                 {
 85                     Q.push(match[v]);
 86                     inque[match[v]]=1;
 87                 }
 88                 else
 89                 {
 90                     u=v;
 91                     while(u!=-1)
 92                     {
 93                         v=pre[u];
 94                         t=match[v];
 95                         match[u]=v;
 96                         match[v]=u;
 97                         u=t;
 98                     }
 99                     return 1;
100                 }
101             }
102         }
103     }
104     return 0;
105 }
106 
107 int solve()
108 {
109     SET(match,-1);
110     int i,ans=0;
111     for(i=1;i<=n;i++) if(match[i]==-1&&BFS(i)) ans++;
112     return ans;
113 }
114 
115 struct edge{
116     int u,v;
117     int flag;
118 }e[433];
119 int m;
120 int main()
121 {
122     while (scanf("%d%d",&n,&m)==2){
123         memset(g,0,sizeof(g));
124         for (int i=1;i<=m;i++)
125         {
126             scanf("%d%d",&e[i].u,&e[i].v);
127             if (g[e[i].u][e[i].v] == 1){
128 
129             }else{
130                 g[e[i].u][e[i].v] = 1;
131                 g[e[i].v][e[i].u] = 1;
132             }
133             e[i]. flag = 0;
134         }
135         memcpy(mat,g,sizeof(g));
136 
137         int ans = solve();
138 
139       //  printf("%d\n",ans);
140        // for (int i=1;i<=n;i++)
141             //printf("%d %d\n",i,match[i]);
142         int res = 0;
143         for (int j=1;j<=m;j++)
144         {
145             int u = e[j].u;
146             int v = e[j].v;
147             memcpy(g,mat,sizeof(mat));
148             for (int i=1;i<=n;i++){
149                 if (g[u][i]){
150                     g[u][i] = 0;
151                     g[i][u] = 0;
152                 }
153                 if (g[v][i])
154                 {
155                     g[v][i] = 0;
156                     g[i][v] = 0;
157                 }
158             }
159             int tmp = solve();
160             if (tmp + 1 < ans)
161             {
162                 e[j].flag = 1;
163                 res++;
164             }
165         }
166 
167 
168         printf("%d\n",res);
169 
170             int fff = 0;
171             for (int i=1;i<=m;i++)
172                 if (e[i].flag == 1){
173                     if (fff)
174                         printf(" ");
175                     fff = 1;
176                     printf("%d",i);
177                 }
178             puts("");
179 
180     }
181     return 0;
182 }
hdu 4687(带花树算法)

 

 

 

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值