Cable TV Network UVA - 1660

将每个节点分成两个点,点与点之间连接容量为1的边,那么这个问题就转换成为最小割的问题,,同时要注意对于那些直接相连接的边要将他们之间添加一条容量为无穷大的边,同时在利用最大流算法进行解决的时候一定要注意以下几点:第一,要注意考虑图的连通性的问题,如果图是不连通的,那么就直接输出结果为0;同时对于那些已经直接连通的边,因为容量已经设置为无穷大的边,那么就可以直接不考虑,具体实现如下:

#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
using namespace std;

const int Inf = 1 << 30;

class Edge{
public:
	int from, to, cap, flow;
	Edge(int fr, int t, int c, int fl) :from(fr), to(t), cap(c), flow(fl){}
};

class Solve{
public:
	int n, m;
	vector<Edge> edge;
	vector<int> G[500];
	int area[55][55];

	void addEdge(int from,int to,int cap){
		edge.push_back(Edge(from, to, cap, 0));
		edge.push_back(Edge(to, from, 0, 0));
		int m = edge.size();
		G[from].push_back(m - 2);
		G[to].push_back(m - 1);
	}

	void Init(){
		edge.clear();
		memset(area, 0, sizeof(area));
		for (int i = 0; i < 500; i++) G[i].clear();
		for (int i = 0; i < n; i++){
			addEdge(i, i + n, 1);
			addEdge(i + n, i, 1);
		}
		for (int i = 0; i < m; i++){
			int a, b;
			scanf("  (%d,%d)",&a,&b);
			area[a][b] = area[b][a] = 1;
			addEdge(a, b + n, Inf);
			addEdge(b, a + n, Inf);
		}
	}

	int MaxFlow(int start,int end){
		int flow = 0;
		bool mark = false;
		for (int i = 0; i < edge.size(); i++) edge[i].flow = 0;
		while (true){
			int Flow[500];
			memset(Flow, 0, sizeof(Flow));
			Flow[start] = Inf;
			int parent[500];
			queue<int> q;
			q.push(start);
			while (!q.empty()){
				int id = q.front();
				q.pop();
				for (int i = 0; i < G[id].size(); i++){
					int ide = G[id][i];
					int to = edge[ide].to;
					if (!Flow[to] && edge[ide].cap>edge[ide].flow){
						Flow[to] = min(Flow[id], edge[ide].cap - edge[ide].flow);
						parent[to] = ide;
						q.push(to);
					}
				}
				if (Flow[end]) break;
			}
			if ((!Flow[end])&&(!mark)) return -1;
			if((Flow[end])&&(!mark)) mark = true;
			if (!Flow[end]) break;
			flow += Flow[end];
			for (int i = end; i != start; i = edge[parent[i]].from){
				edge[parent[i]].flow += Flow[end];
				edge[parent[i] ^ 1].flow -= Flow[end];
			}
		}
		return flow;
	}

	int Deal(){
		Init();
		int ans=Inf;
		for (int j = 1; j < n; j++){
			if (!area[0][j]){
				int ans2 = MaxFlow(0, j+n);
				if (ans2 == -1){
					ans = 0;
					break;
				}
				ans = min(ans, ans2);
			}
		}
		if (ans >= (n - 1)) return n;
		else return ans;
	}
};

int main(){
	Solve a;
	while (scanf("%d %d",&a.n,&a.m)!=EOF){
		int res = a.Deal();
		cout << res << endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值