http://acm.hdu.edu.cn/showproblem.php?pid=4687
题意:找到所有的最大匹配,然后输出不在任何最大匹配中的边的序号
解法:贴板题,一般图的最大匹配,带花树算法,然后求暴力枚举去掉一条边的最大匹配数与原最大匹配数比较
赛后才知道带花树算法
直接用的标程的带花树算法的模板。。。
1 /** 2 *版题。。。之前不知道这个算法。。。 3 *一般图的最大匹配:带花树算法 4 *暴力枚举去掉一条边的最大匹配数与原最大匹配数比较 5 * 6 *@Author: xiaohai 7 */ 8 //#pragma comment(linker, "/STACK:102400000,102400000") 9 #include<cstdio> 10 #include<iostream> 11 #include<cstring> 12 #include<string> 13 #include<cmath> 14 #include<set> 15 #include<list> 16 #include<map> 17 #include<iterator> 18 #include<cstdlib> 19 #include<vector> 20 #include<queue> 21 #include<stack> 22 #include<algorithm> 23 #include<functional> 24 using namespace std; 25 typedef long long LL; 26 #define ROUND(x) round(x) 27 #define FLOOR(x) floor(x) 28 #define CEIL(x) ceil(x) 29 const int maxn=45; 30 const int maxm=300; 31 const int inf=0x3f3f3f3f; 32 const LL inf64=0x3f3f3f3f3f3f3f3fLL; 33 const double INF=1e30; 34 const double eps=1e-6; 35 int n,m,cnt; 36 int mtx[maxn][maxn]; 37 struct Edge 38 { 39 int u,v; 40 Edge(int _u,int _v):u(_u),v(_v) {} 41 }; 42 vector<Edge> edge; 43 /** 44 *一般图的最大基数匹配:带花树算法 45 *输入:g[][],n(输入从0到n-1,用addEdge()加边) 46 *输出:gao()(最大匹配数),match[](匹配) 47 */ 48 struct Matching 49 { 50 deque<int> Q; 51 int n; 52 //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点 53 bool g[maxn][maxn],inque[maxn],inblossom[maxn],inpath[maxn]; 54 int match[maxn],pre[maxn],base[maxn]; 55 56 //找公共祖先 57 int findancestor(int u,int v) 58 { 59 memset(inpath,0,sizeof(inpath)); 60 while(1) 61 { 62 u=base[u]; 63 inpath[u]=true; 64 if(match[u]==-1)break; 65 u=pre[match[u]]; 66 } 67 while(1) 68 { 69 v=base[v]; 70 if(inpath[v])return v; 71 v=pre[match[v]]; 72 } 73 } 74 75 //压缩花 76 void reset(int u,int anc) 77 { 78 while(u!=anc) 79 { 80 int v=match[u]; 81 inblossom[base[u]]=1; 82 inblossom[base[v]]=1; 83 v=pre[v]; 84 if(base[v]!=anc)pre[v]=match[u]; 85 u=v; 86 } 87 } 88 89 void contract(int u,int v,int n) 90 { 91 int anc=findancestor(u,v); 92 //SET(inblossom,0); 93 memset(inblossom,0,sizeof(inblossom)); 94 reset(u,anc); 95 reset(v,anc); 96 if(base[u]!=anc)pre[u]=v; 97 if(base[v]!=anc)pre[v]=u; 98 for(int i=1; i<=n; i++) 99 if(inblossom[base[i]]) 100 { 101 base[i]=anc; 102 if(!inque[i]) 103 { 104 Q.push_back(i); 105 inque[i]=1; 106 } 107 } 108 } 109 110 bool dfs(int S,int n) 111 { 112 for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i; 113 Q.clear(); 114 Q.push_back(S); 115 inque[S]=1; 116 while(!Q.empty()) 117 { 118 int u=Q.front(); 119 Q.pop_front(); 120 for(int v=1; v<=n; v++) 121 { 122 if(g[u][v]&&base[v]!=base[u]&&match[u]!=v) 123 { 124 if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n); 125 else if(pre[v]==-1) 126 { 127 pre[v]=u; 128 if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1; 129 else 130 { 131 u=v; 132 while(u!=-1) 133 { 134 v=pre[u]; 135 int w=match[v]; 136 match[u]=v; 137 match[v]=u; 138 u=w; 139 } 140 return true; 141 } 142 } 143 } 144 } 145 } 146 return false; 147 } 148 149 void init(int n) 150 { 151 this->n = n; 152 memset(match,-1,sizeof(match)); 153 memset(g,0,sizeof(g)); 154 } 155 156 void addEdge(int a, int b) 157 { 158 ++a; 159 ++b; 160 g[a][b] = g[b][a] = 1; 161 } 162 163 int gao() 164 { 165 int ans = 0; 166 for (int i = 1; i <= n; ++i) 167 if (match[i] == -1 && dfs(i, n)) 168 ++ans; 169 return ans; 170 } 171 }; 172 Matching match; 173 void init() 174 { 175 edge.clear(); 176 memset(mtx,0,sizeof(mtx)); 177 } 178 void input() 179 { 180 // scanf("%d%d",&n,&m); 181 match.init(n); 182 while(m--) 183 { 184 int u,v; 185 scanf("%d%d",&u,&v); 186 --u,--v; 187 mtx[u][v]=mtx[v][u]=1; 188 match.addEdge(u,v); 189 edge.push_back(Edge(u,v)); 190 } 191 } 192 void solve() 193 { 194 cnt=match.gao(); 195 vector<int> ans; 196 for(int k=0; k<edge.size(); k++) 197 { 198 int u=edge[k].u,v=edge[k].v; 199 match.init(n); 200 for(int i=0; i<n; i++) 201 { 202 for(int j=0; j<n; j++) 203 { 204 if(i!=u&&i!=v&&j!=u&&j!=v) 205 { 206 match.g[i+1][j+1]=mtx[i][j]; 207 } 208 } 209 } 210 if(match.gao()<cnt-1) ans.push_back(k+1); 211 } 212 printf("%d ",ans.size()); 213 for(int i=0; i<ans.size(); i++) 214 { 215 printf("%d",ans[i]); 216 if(i<ans.size()-1) printf(" "); 217 } 218 puts(""); 219 } 220 int main() 221 { 222 std::ios_base::sync_with_stdio(false); 223 // freopen("in.cpp","r",stdin); 224 while(~scanf("%d%d",&n,&m)) 225 { 226 init(); 227 input(); 228 solve(); 229 } 230 return 0; 231 }