题意:
给定一个简单图,询问哪些边如果选择的话会使得剩下的图中最大的匹配数减少。
思路:
先求出最大匹配数,然后枚举每一条边,再做最大匹配看是否为最大匹配数.求无向图的最大匹配数,带花树算法。模板,等待学习中>
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 }