poj3041
最小覆盖=最大匹配,有时间看一下证明过程
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 #include <list> 9 #include <ctime> 10 #include <set> 11 #include <queue> 12 #include <cstring> 13 #include <cstdio> 14 using namespace std; 15 #define INT_MAX 10000000 16 #define N 1005 17 #define CLR(arr, what) memset(arr, what, sizeof(arr)) 18 int capacity[N][N]; //容量 19 int flow[N]; //残余流量 20 int pre[N]; //前趋 21 int n; //节点个数 22 23 queue<int> Q; 24 25 int BFS(int src, int des) { 26 //初始化 27 while (!Q.empty()) { 28 Q.pop(); 29 } 30 for (int i = 1; i < n + 1; i++) { 31 pre[i] = -1; 32 } 33 pre[src] = 0; 34 flow[src] = INT_MAX; //初始化源点的流量为无穷大 35 Q.push(src); 36 while (!Q.empty()) { 37 int index = Q.front(); 38 Q.pop(); 39 if (index == des) { //找到了增广路径 40 break; 41 } 42 for (int i = 1; i < n + 1; i++) { 43 if (i != src && capacity[index][i] > 0 && pre[i] == -1) { 44 pre[i] = index; 45 //增广路残容流量 46 flow[i] = min(capacity[index][i], flow[index]); 47 Q.push(i); 48 } 49 } 50 } //while 51 if (pre[des] == -1) { 52 return -1; //残留图中不存在增广路径 53 } else { 54 return flow[des]; 55 } 56 } 57 58 int MaxFlow(int src, int des) { 59 int aug = 0; 60 int sumflow = 0; 61 while ((aug = BFS(src, des)) != -1) { 62 int k = des; //利用前驱寻找路径 63 while (k != src) { 64 int last = pre[k]; 65 capacity[last][k] -= aug; 66 capacity[k][last] += aug; 67 k = last; 68 } 69 sumflow += aug; 70 } 71 return sumflow; 72 } 73 struct node { 74 string in, out; 75 int cap; 76 }; 77 int checkin(string & a, string& b) { 78 int sz = a.size(); 79 bool judge = 1; 80 for (int i = 0; i < sz; i++) { 81 if (a[i] == '2' || b[i] == '2') { 82 continue; 83 } else if (a[i] != b[i]) { 84 judge = 0; 85 break; 86 } 87 } 88 if (1 == judge) 89 return 1; 90 return 0; 91 } 92 93 int cur[N]; //后继 94 int dis[N]; //距离 95 int gap[N]; //层结点数(用于间隙优化) 96 int SAP(int s, int t) //源点、汇点、结点数 97 { 98 CLR(gap, 0); 99 CLR(cur, 0); 100 CLR(dis, 0); 101 int u = pre[s] = s, maxflow = 0, aug = INT_MAX; 102 int v; 103 gap[0] = n; 104 while (dis[s] < n) { 105 bool flag = false; 106 for (v = cur[u]; v <= n; ++v) //寻找允许弧 107 { 108 if (capacity[u][v] > 0 && dis[u] == dis[v] + 1) { 109 flag = true; 110 break; 111 } 112 } 113 if (flag) //找到允许弧 114 { 115 pre[v] = u; 116 cur[u] = v; 117 aug = min(aug, capacity[u][v]); 118 u = v; 119 if (v == t) //找到完整增广路 120 { 121 maxflow += aug; 122 for (v = t; v != s; v = pre[v]) //更新残留网络 123 { 124 capacity[pre[v]][v] -= aug; //正向边 125 capacity[v][pre[v]] += aug; //反向边 126 } 127 aug = INT_MAX; 128 u = s; //重新从源点寻找 129 } 130 } else //找不到允许弧 131 { 132 int mindis = n; 133 for (v = 1; v <= n; ++v) //重新标号 134 { 135 if (capacity[u][v] && mindis > dis[v]) { 136 cur[u] = v; 137 mindis = dis[v]; 138 } 139 } 140 if (--gap[dis[u]] == 0) //更新断层 + 判断是否断层(间隙优化) 141 break; 142 gap[dis[u] = mindis + 1]++; //更新断层 143 u = pre[u]; //当前弧优化 144 } 145 } 146 return maxflow; 147 } 148 149 inline void addedge(int x, int y, int c) { // add an arc(x -> y, c); vertex: 0 ~ n-1; 150 capacity[x][y] = c; 151 } 152 153 int main() { 154 int _n, k, u, v; 155 char tmp; 156 cin >> _n; 157 n = _n * 2 + 2; 158 cin >> k; 159 for (int i = 0; i < _n; i++) { 160 addedge(0, i + 1, 1); 161 addedge(_n + i + 1, n - 1, 1); 162 } 163 for (int i = 0; i < k; i++) { 164 scanf("%d %d", &u, &v); 165 addedge(u, v + _n, 1); 166 } 167 int sum = MaxFlow(0, n - 1); 168 //int sum = SAP( 0, curn - 1); 169 cout << sum << endl; 170 return 0; 171 }