题目链接:https://vjudge.net/problem/HDU-4687
知识点: 带花树开花算法
解题思路:
先求出原来的一般图的最大匹配数\(iCnt\). 然后枚举每一个组合,尝试去掉图中所有以这个组合中任意一点为端点的边,求出此时的最大匹配数\(tCnt\),如果\(tCnt
AC代码:
1 #include
2 using namespace std;
3 typedef pair<int,int> P ;
4 const int maxn = 40+5, maxm = 150;
5 int N,M;
6 bool Graph[maxn][maxn],G[maxn][maxn];
7 int Match[maxn];
8 bool InQueue[maxn],InPath[maxn],InBlossom[maxn];
9 int Head,Tail;
10 int Queue[maxn];
11 int Start,Finish;
12 int NewBase;
13 int Father[maxn],Base[maxn];
14
15 P inp[maxm];
16
17 void Push(int u){
18 Queue[Tail]=u;
19 Tail++;
20 InQueue[u]=true;
21 }
22 int Pop(){
23 int res=Queue[Head];
24 Head++;
25 return res;
26 }
27 int FindCommonAncestor(int u,int v){
28 memset(InPath,false,sizeof(InPath));
29 while(1){
30 u=Base[u];
31 InPath[u]=true;
32 if(u==Start) break;
33 u=Father[Match[u]];
34 }
35 while(1){
36 v=Base[v];
37 if(InPath[v]) break;
38 v=Father[Match[v]];
39 }
40 return v;
41 }
42 void ResetTrace(int u){
43 int v;
44 while(Base[u]!=NewBase){
45 v=Match[u];
46 InBlossom[Base[u]]=InBlossom[Base[v]]=true;
47 u=Father[v];
48 if(Base[u]!=NewBase) Father[u]=v;
49 }
50 }
51 void BloosomContract(int u,int v){
52 NewBase = FindCommonAncestor(u,v);
53 memset(InBlossom,false,sizeof(InBlossom));
54 ResetTrace(u); ResetTrace(v);
55 if(Base[u]!=NewBase) Father[u]=v;
56 if(Base[v]!=NewBase) Father[v]=u;
57 for(int tu=1;tu<=N;tu++){
58 if(InBlossom[Base[tu]]){
59 Base[tu]=NewBase;
60 if(!InQueue[tu]) Push(tu);
61 }
62 }
63 }
64 void FindAugmentingPath(){
65 memset(InQueue,false,sizeof(InQueue));
66 memset(Father,0,sizeof(Father));
67 for(int i=1;i<=N;i++) Base[i]=i;
68 Head=Tail=1;
69 Push(Start);
70 Finish=0;
71 while(Head<Tail){
72 int u=Pop();
73 for(int v=1;v<=N;v++){
74 if(Graph[u][v]&&(Base[u]!=Base[v])&&(Match[u]!=v)){
75 if((v==Start)||(Match[v]>0)&&(Father[Match[v]]>0))
76 BloosomContract(u,v);
77 else if(Father[v]==0){
78 Father[v]=u;
79 if(Match[v]>0) Push(Match[v]);
80 else{
81 Finish=v;
82 return;
83 }
84 }
85 }
86 }
87 }
88 }
89 void AugumentPath(){
90 int u,v,w;
91 u=Finish;
92 while(u>0){
93 v=Father[u];
94 w=Match[v];
95 Match[v]=u;
96 Match[u]=v;
97 u=w;
98 }
99 }
100 void Edmonds(){
101 memset(Match,0,sizeof(Match));
102 for(int u=1;u<=N;u++){
103 if(Match[u]==0){
104 Start =u;
105 FindAugmentingPath();
106 if(Finish>0) AugumentPath();
107 }
108 }
109 }
110
111 int main(){
112 int u,v;
113 while(scanf("%d%d",&N,&M)==2){
114 memset(G,false,sizeof(G));
115 memset(Graph,false,sizeof(Graph));
116 for(int i=1;i<=M;i++){
117 scanf("%d%d",&u,&v);
118 inp[i]=make_pair(u,v);
119 Graph[u][v]=Graph[v][u]=G[u][v]=G[v][u]=true;
120 }
121 Edmonds();
122 int iCount=0;
123 for(int u=1;u<=N;u++){
124 if(Match[u]>0) iCount++;
125 }iCount/=2;
126 vector<int> ans;
127 for(int i=1;i<=M;i++){
128 int u=inp[i].first,v=inp[i].second;
129 for(int j=1;j<=N;j++) Graph[u][j]=Graph[j][u]=Graph[v][j]=Graph[j][v]=false;
130 Edmonds();
131 int tCount=0;
132 for(int u=1;u<=N;u++){
133 if(Match[u]>0) tCount++;
134 }tCount/=2;
135 if(tCount1) ans.push_back(i);
136 for(int j=1;j<=N;j++){
137 Graph[u][j]=G[u][j];
138 Graph[j][u]=G[j][u];
139 Graph[v][j]=G[v][j];
140 Graph[j][v]=G[j][v];
141 }
142 }
143 int sz=ans.size();
144 printf("%d\n",sz);
145 for(int i=0;i){
146 if(i!=0) printf(" ");
147 printf("%d",ans[i]);
148 }
149 printf("\n");
150 }
151 return 0;
152 }