uva 11248

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=565&page=show_problem&problem=2205

题意:见大白书368页

要注意的地方在大白书上面也都说了,不过做的时候被求割点卡了。。之前没做过- -。长了见识。

求割的那部分是这样的:因为最后已经走不过去了,所以如果某条边起点能走到,终点走不到,那说明它就是在最小割的集合里面,否则就还有增广路。

/*
 * ThinkingLion.cpp
 *
 *  Created on: 2014年11月25日
 *      Author: dell
 */
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define clr1(a) memset(a,0,sizeof(a))
#define clr2(a) memset(a,-1,sizeof(a))
#define ll __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) {
	return b ? gcd(b, a % b) : a;
}
template<class T> T lcm(T a, T b) {
	return a / gcd(a, b) * b;
}
template<class T> inline T Min(T a, T b) {
	return a < b ? a : b;
}
template<class T> inline T Max(T a, T b) {
	return a > b ? a : b;
}
using namespace std;
int n, e, c;
#define N 110
struct Edge {
	int from, to, cap, flow;
};
struct Dinic {
	int n, m, s, t;
	vector<Edge> edges;
	vector<Edge> edtmp;
	vector<int> G[N];
	vector<int> cut;
	Edge able[N * N * 2];
	int p[N];
	bool vis[N];
	int d[N];
	int cur[N];
	int k;
	int flow;
	void Init(int n, int m, int s, int t) {
		this->n = n;
		this->m = m;
		this->s = s;
		this->t = t;
		for (int i = 0; i <= N; i++)
			G[i].clear();
		edges.clear();
		flow = 0;
	}
	void addEdge(int u, int v, int cap) {
		edges.push_back((Edge ) { u, v, cap, 0 });
		edges.push_back((Edge ) { v, u, 0, 0 });
		m = edges.size();
		G[u].push_back(m - 2);
		G[v].push_back(m - 1);
	}
	bool BFS() {
		memset(vis, 0, sizeof vis);
		queue<int> q;
		q.push(s);
		vis[s] = 1;
		d[s] = 0;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			for (int i = 0; i < (int) G[u].size(); i++) {
				Edge &e = edges[G[u][i]];
				if (e.cap > e.flow && !vis[e.to]) {
					vis[e.to] = 1;
					d[e.to] = d[u] + 1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	int DFS(int x, int a) {
		if (x == t || a == 0)
			return a;
		int flow = 0, f;
		for (int &i = cur[x]; i < (int) G[x].size(); i++) {
			Edge &e = edges[G[x][i]];
			if (d[x] + 1 == d[e.to]
					&& (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
				e.flow += f;
				edges[G[x][i] ^ 1].flow -= f;
				flow += f;
				a -= f;
				if (a == 0)
					break;
			}
		}
		return flow;
	}
	int maxFlow() {
		while (BFS()) {
			memset(cur, 0, sizeof cur);
			flow += DFS(s, INF);
			if (flow >= c)
				return true;
		}
		return false;
	}
	void getcut() {
		BFS();
		cut.clear();
		for (int i = 0; i < (int) edges.size(); i += 2) {
			if (vis[edges[i].from] && !vis[edges[i].to] && edges[i].cap > 0) {
				cut.push_back(i);
			}
		}
	}
	
	void getTable() {
		getcut();
		edtmp.clear();
		for (int i = 0; i < (int) edges.size(); i++)
			edtmp.push_back(edges[i]);
		int lastflow = flow;
		k = 0;
		for (int i = 0; i < (int) cut.size(); i++) {
			edges[cut[i]].cap = edges[cut[i]].flow + c;
			if (maxFlow())
				able[k++] = edges[cut[i]];
			flow = lastflow;
			edges.clear();
			for (int j = 0; j < (int) edtmp.size(); j++)
				edges.push_back(edtmp[j]);
		}
	}
};
Dinic solver;
bool cmp(Edge a, Edge b) {
	if (a.from < b.from)
		return true;
	else if (a.from == b.from && a.to < b.to)
		return true;
	return false;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	int kas = 1;
	while (scanf("%d%d%d", &n, &e, &c) != EOF && n + e + c) {
		solver.Init(n, e, 1, n);
		int u, v, cap;
		for (int i = 0; i < e; i++) {
			scanf("%d%d%d", &u, &v, &cap);
			solver.addEdge(u, v, cap);
		}
		printf("Case %d: ", kas++);
		if (solver.maxFlow() || c == 0)
			printf("possible\n");
		else {
			solver.getTable();
			if (solver.k <= 0)
				printf("not possible\n");
			else {
				sort(solver.able, solver.able + solver.k, cmp);
				printf("possible option:(%d,%d)", solver.able[0].from,
						solver.able[0].to);
				for (int i = 1; i < solver.k; i++) {
					printf(",(%d,%d)", solver.able[i].from, solver.able[i].to);
				}
				printf("\n");
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值