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 }

from kakamilan

原文地址:https://www.cnblogs.com/kakamilan/p/3070139.html