uva1660电视网络-最小割最大流

题意:

求无向图的点连通度(最少删除几个点,使得图不连通)

思路:

求最小割(最大流)。每个点只能被用一次,否则可能有多条增广路公用同一个点,而其实删掉这一个点就足够破坏这些路了。点只能用一次,想到拆点法。然后最大流算法就行了。
写了几个不同算法熟悉一下,结果ISAP的时候卡住了,怎么答案老不对,原来是由于用了拆点法n变成了2n。

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 500+10;
int n, m;
int u1[maxn], v1[maxn];

// 图
struct Edge{
	int u, v, cap, flow;
	Edge(int a, int b, int c, int d):u(a),v(b),cap(c),flow(d){}
}; 
vector<Edge> edges;
vector<int> G[maxn]; 
void addEdge(int u, int v, int cap){
	edges.push_back(Edge(u,v,cap,0));
	edges.push_back(Edge(v,u,0,0));		// 反向弧
	int m = edges.size();
	G[u].push_back(m-2);
	G[v].push_back(m-1); 
}
void init(){
	for(int i = 0; i < maxn; ++i) G[i].clear();
	edges.clear();
	for(int i = 0; i < n; ++i) addEdge(i, i+n, 1);
	for(int i = 0; i < m; ++i){
		addEdge(u1[i]+n, v1[i], INF);
		addEdge(v1[i]+n, u1[i], INF);
	}
}

// ---------------- Q: ISAP 怎么了? 
int Gap[maxn], cur[maxn], pre[maxn], dis[maxn];

void bfs(int s, int t){
	memset(dis, -1, sizeof(dis));
	memset(Gap, 0, sizeof(Gap));
	dis[t] = 0; 
	Gap[0] = 1;
	queue<int> Q;
	Q.push(t);		// 反向
	while(!Q.empty()){
		int x = Q.front(); Q.pop();
		for(int i = 0; i < G[x].size(); ++i){
			Edge& e = edges[G[x][i]^1];
			if(dis[e.u] == -1){
				dis[e.u] = dis[x] + 1;
				++Gap[dis[e.u]];
				Q.push(e.u);
			}
		}
	}
}
int augument(int s, int t){
	int f = INF;
	for(int u = t; u != s; u = edges[pre[u]].u){
		Edge& e = edges[pre[u]];
		f = min(f, e.cap - e.flow);
	}
	for(int u = t; u != s; u = edges[pre[u]].u){
		edges[pre[u]].flow += f;
		edges[pre[u]^1].flow -= f;
	}
	return f;
}
int ISAP(int s, int t){
	bfs(s, t);
	memset(cur, 0, sizeof(cur));
	int u = s;
	int ans = 0;
	while(dis[s] < 2*n-2){ // 注意乘2!,-2是因为从出点到入点 
		if(u == t){
			ans += augument(s, t);
			u = s;
		}
		bool advanced = false;
		for(int& i = cur[u]; i < G[u].size(); ++i){
			Edge& e = edges[G[u][i]];
			if(dis[u] == dis[e.v] + 1&&e.cap > e.flow){
				pre[e.v] = G[u][i];
				u = e.v;
				advanced = true;
				break;
			}
		}
		if(!advanced){
			int d = 2*n-3;
			for(int i = 0; i < G[u].size(); ++i){
				Edge& e = edges[G[u][i]];
				if(e.cap > e.flow) d = min(d, dis[e.v]);
			}
			if(--Gap[dis[u]] == 0) break;
			dis[u] = d + 1;
			++Gap[dis[u]];
			cur[u] = 0;
			if(u != s) u = edges[pre[u]].u;
		}
	}
	return ans;
}


int main()
{
	//freopen("in.txt","r",stdin);
	while(scanf("%d%d",&n,&m) == 2){
		for(int i = 0; i < m; ++i)scanf(" (%d,%d)",&u1[i],&v1[i]);
		int ans = INF;
		for(int i = 1; i < n; ++i){
			init();
			ans = min(ans, ISAP(n, i));
			//printf("%d -> %d, flow = %d\n",n,i,ans);
		}
		if(ans >= INF) ans = n;
		printf("%d\n",ans);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/CY05627/article/details/91456327