一.原题链接:http://poj.org/problem?id=1966
二.题目大意:给你一个很裸的网络,让你判断最少去掉多少个点能够使其不连通。注意是无向图。
三.思路:枚举每个源点和汇点,求每次的最小割点集。取一个最小的,如果是完全图,每次求出的网络流肯定是INF,此时没有割点集,题目要求输出顶点数。
注意要枚举每个源点和汇点,不能固定源点,因为源点有可能是割点,题目测试数据有问题:
比如下图:
如果0为源点,跑最大流,出来的结果是INF,然而其实0就是那个最小割的点。
最小割点集合不懂建图的:详情请看http://blog.csdn.net/h992109898/article/details/51232440
四.代码:
#include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <cstdlib> using namespace std; const int INF = 0x3f3f3f3f, MAX_N = 55; class Dinic { public: struct Edge { int v, w, next; }; int cnt, head[MAX_N*2], dist[MAX_N*2], s, t; Edge edges[MAX_N*MAX_N*2]; void init(int is, int it) { cnt = 0; s = is, t = it; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int weight) { edges[cnt] = (Edge){v, weight, head[u]}; head[u] = cnt++; edges[cnt] = (Edge){u, 0, head[v]}; head[v] = cnt++; } bool BFS() { int i, cur; queue <int> que; que.push(s); memset(dist, -1, sizeof(dist)); dist[s] = 0; while(!que.empty()){ cur = que.front(); que.pop(); for(i = head[cur]; i != -1; i = edges[i].next) if(-1 == dist[edges[i].v] && edges[i].w){ dist[edges[i].v] = dist[cur] + 1; que.push(edges[i].v); } } return dist[t] != -1; } int DFS(int start, int curFlow) { if(start == t) return curFlow; int i, minFlow = 0, v, temp; for(i = head[start]; i != -1; i = edges[i].next){ v = edges[i].v; if(dist[start] == dist[v] - 1 && edges[i].w > 0){ temp = DFS(v, min(edges[i].w, curFlow)); edges[i].w -= temp; edges[i^1].w += temp; curFlow -= temp; minFlow += temp; if(0 == curFlow) break; } } if(0 == minFlow) dist[start] = -2; return minFlow; } int maxFlow() { int res = 0; while(BFS()){ res += DFS(s, INF); } return res; } }G; bool edges[MAX_N][MAX_N]; int edgeNum, nodeNum; int netFlow(int s, int t) { G.init(s + nodeNum, t); int i, j; for(i = 0; i < nodeNum; i++){ G.addEdge(i, i + nodeNum, 1); for(j = 0; j < nodeNum; j++) if(edges[i][j]) G.addEdge(i + nodeNum, j, INF); } return G.maxFlow(); } int main() { //freopen("in.txt", "r", stdin); int i, j, u, v, res; while(~scanf("%d%d", &nodeNum, &edgeNum)){ memset(edges, 0, sizeof(edges)); for(i = 0; i < edgeNum; i++){ scanf(" (%d,%d)", &u, &v); edges[u][v] = edges[v][u] = true; } res = INF; for(i = 0; i < nodeNum; i++) for(j = 0; j < nodeNum; j++) if(!edges[i][j] && j != i) res = min(res, netFlow(i, j)); if(res == INF){ if(!nodeNum || !edgeNum && nodeNum != 1) printf("0\n"); else printf("%d\n", nodeNum); } else printf("%d\n", res); } return 0; }