Uva 11248 Frequency Hopping

本文介绍了一个最大流问题的解决方案,通过使用Dinic算法求解原始最大流,并在此基础上进行优化,寻找最小割来调整边容量使得流量能达到指定值C。文章详细解释了如何通过枚举最小割中的边来寻找可行选项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

坑爹啊 c可能为0......又是两小时

先求出最大流 然后可能修改的边只能是最小割的边, 枚举没条边

保存修改之前的最大流 每次枚举时不重新找最大流直接在初始最大流上跑

只要最大流超过c就可以停止了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long ll;

const int MAXN = 107;
const ll INF = 1LL << 51;
struct Dinic {
	struct Edge {
		int from, to, flow;
		ll cap;
		Edge() {};
		Edge(int from, int to, ll cap, int flow):from(from), to(to), cap(cap), flow(flow) {}
		bool operator < (const Edge &e) const {
			return from < e.from || from == e.from && to < e.to;
		}
	};
	vector<Edge> edges, estmp;
	vector<int> G[MAXN];
	vector<int> cut;
	Edge able[MAXN*MAXN*2];
	int d[MAXN], cur[MAXN];
	int n, m, s, t;
	int nable;
	ll c, flow;
	bool vis[MAXN];
	
	void init(int n, ll c, int s, int t) {
		this->n = n, this->c = c, this->s = s, this->t = t;
		for(int i = 1; i <= n; i++) G[i].clear();
		edges.clear();
		flow = 0;
	}

	void addedge(int u, int v, ll 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));
		memset(d, -1, sizeof(d));
		queue<int> q;
		q.push(s);
		d[s] = 0;
		vis[s] = true;
		while( !q.empty()) {
			int u = q.front(); q.pop();
			int i, sz = G[u].size();
			for(i = 0; i < sz; i++) {
				Edge e = edges[ G[u][i]];
				if( !vis[e.to] && e.cap > e.flow) {
					vis[e.to] = true;
					d[e.to] = d[u] + 1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}

	ll dfs(int u, ll limit) {
		if(u == t || limit == 0) return limit;
		int flow = 0, f, sz = G[u].size();
		for(int &i = cur[u]; i < sz; i++) {
			
			Edge &e = edges[ G[u][i]];
			if(d[u] + 1 == d[e.to] && (f = dfs(e.to, min(limit, e.cap - e.flow) ) ) > 0) {
				e.flow += f;
				edges[ G[u][i] ^ 1].flow -= f;
				flow += f;
				limit -= f;
				if(limit == 0) break;
			}
		}
		return flow;
	}

	bool Maxflow() {
		while( bfs()) {
			memset(cur, 0, sizeof(cur));
			flow += dfs(s, INF);
			if(flow >= c) return true;
		}
		return false;
	}
	void getcut() {
		cut.clear();
		int i, sz = edges.size();
		for(i = 0; i < sz; i += 2) {
			if(vis[ edges[i].from] && !vis[ edges[i].to]) {
				cut.push_back(i);
			}
		}
	}

	void getable() {
		getcut();
		nable = 0;
		estmp.clear();
		int i, sz = edges.size();
		for(i = 0; i <sz; i++) estmp.push_back(edges[i]);
		
		ll lastflow = flow;
		sz = cut.size();
		for(i = 0; i < sz; i++) {
			edges[cut[i]].cap = edges[cut[i]].flow + c;

			if(Maxflow()) able[nable++] = edges[cut[i]];

			flow = lastflow;
			int j, csz = estmp.size();
			edges.clear();
			for(j = 0; j < csz; j++) edges.push_back(estmp[j]);
		}
	}
}Dic;

int main() {
	int n, e, id = 0;
	ll c, cap;
	while(~scanf("%d%d%lld", &n, &e, &c), n|e|c) {
		if(c < 0) while(1);
		Dic.init(n, c, 1, n);
		int i, u, v;
		for(i = 1; i <= e; i++) {
			scanf("%d%d%lld", &u, &v, &cap);
			Dic.addedge(u, v, cap);
		}
		printf("Case %d: ", ++id);
		if(Dic.Maxflow() || c == 0) puts("possible");
		else {
			Dic.getable();
			if(Dic.nable <= 0) puts("not possible");
			else {
				sort(Dic.able, Dic.able + Dic.nable);
				printf("possible option:(%d,%d)", Dic.able[0].from, Dic.able[0].to);
				for(i = 1; i < Dic.nable; i++)
					printf(",(%d,%d)", Dic.able[i].from, Dic.able[i].to);
				puts("");
			}
		}	
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值