UVA11248 Frequency Hopping 题解

先最大流一次,如果此时流量大于等于 CC,那我们一定可以通过将一些边的流量减小而到达 CC

如果不行,我们考虑枚举每一条流满的边,将容量设置为 ++\infty 后再跑一次。容易发现如果一条边没有满流那么增加容量没有意义。他的流量已经被前面的边限制了。

这样我们每次更改容量,重新跑最大流即可。

#pragma GCC optimize("-Ofast,fast-math,-inline")
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

#define int long long

const int N = 3e4 + 5;

int n, m, p;
int e[N], h[N], c[N], ne[N], idx;
int e2[N], h2[N], c2[N], ne2[N], idx2;
int num[N];

inline void add(int u, int v, int w)
{
	e[idx] = v, c[idx] = w, ne[idx] = h[u], h[u] = idx++;
	e[idx] = u, c[idx] = 0, ne[idx] = h[v], h[v] = idx++;
}

inline void add2(int u, int v, int w)
{
	e2[idx2] = v, c2[idx2] = w, ne2[idx2] = h2[u], h2[u] = idx2++;
	e2[idx2] = u, c2[idx2] = 0, ne2[idx2] = h2[v], h2[v] = idx2++;
}

int U[N], V[N];

class Maximum_Flow
{
public:
	int d[N], cur[N];
	bool bfs()
	{
		for (int i = 1; i <= n; i++) d[i] = -1, cur[i] = -1;
		queue<int> q;
		d[1] = 0;
		cur[1] = h2[1];
		q.push(1);
		while (q.size())
		{
			int u = q.front();
			q.pop();
			for (int i = h2[u]; ~i; i = ne2[i])
			{
				int j = e2[i];
				if (d[j] == -1 && c2[i] > 0)
				{
					d[j] = d[u] + 1;
					cur[j] = h2[j];
					if (j == n) return 1;
					q.push(j);
				}
			}
		}
		return 0;
	}
	int dfs(int u, int lim)
	{
		if (u == n) return lim;
		int sum = 0;
		for (int i = cur[u]; ~i && sum < lim; i = ne2[i])
		{
			cur[u] = i;
			int j = e2[i];
			if (d[j] == d[u] + 1 && c2[i] > 0)
			{
				int q = dfs(j, min(lim - sum, c2[i]));
				//printf("!: %lld %lld %lld %lld\n", u, j, p, min(lim - sum, c2[i]));
				if (!q) d[j] = -1;
				else
				{
					sum += q;
					c2[i] -= q;
					c2[i ^ 1] += q;
				}
				
			}
		}
		return sum;
	}
	int dinic()
	{
		int res = 0;
		while (bfs())
		{
			int k;
			while (k = dfs(1, 2e9)) res += k;
		}
		return res;
	}
}DNC;

int c3[N];

signed main()
{
	int css = 0;
	while (scanf("%lld%lld%lld", &n, &m, &p))
	{
		css++;
		if (!n && !m && !p) break;
		for (int i = 0; i <= n; i++)
		{
			h[i] = h2[i] = -1;
		}
		idx = idx2 = 0;
		for (int i = 1; i <= m; i++)
		{
			int u, v, w;
			scanf("%lld%lld%lld", &u, &v, &w);
			add(u, v, w);
			add2(u, v, w);
			num[i] = idx2 - 2;
			U[i] = u, V[i] = v;
		}
		vector<pair<int, int> > ans;
		int ps = DNC.dinic();
		if (ps >= p)
		{
			printf("Case %lld: possible\n", css);
			continue;
		}
		else
		{
			for (int i = 0; i < N; i++) c3[i] = c2[i];
			for (int i = 1; i <= m; i++)
			{
				int g = num[i];
				if (c3[g] == 0)
				{
					// 流满,将这条边容量改为 INF
					for (int j = 0; j <= idx; j++)
					{
						c2[j] = c[j];
					}
					c2[g] = 2e9;
					if (DNC.dinic() >= p)
					{
						ans.emplace_back(make_pair(U[i], V[i]));
					}
				}
			}
		}
		sort(ans.begin(), ans.end());
		if (ans.size() == 0) printf("Case %lld: not possible\n", css);
		else
		{
			printf("Case %lld: possible option:", css);
			for (int i = 0; i + 1 < ans.size(); i++)
			{
				printf("(%lld,%lld),", ans[i].first, ans[i].second);
			}
			printf("(%lld,%lld)\n", ans.back().first, ans.back().second);
		}
	}
	return 0;
}
posted @   HappyBobb  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示