题意:
给定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 }