UVA - 10480 Sabotage 最大流最小割+ 输出割边集

 因为是pdf形式我就不把题目弄上来了,就写主要需要注意的两点:

 1.输出割边集。正确的写法是先按照源点开始dfs,如果某一边得剩余流量大于0就继续向下探索另一个点并标记,等于零就跳过这一边。最后把所有的边找出来,看看如果有两个点标记不一样(一个标记了一个没标记),就输出这个边就好了(因为我们建立的是双向便所以别忘了遍历时每次加2)。

   但是我在没看这种做法得时候,我是想把所有得剩余流量是0得边输出的,但这样其实不对的。比如1->3(0) 1->4(1) 4->3(1) 3->...这种情况下,虽然1到3剩余流量为0,但其实这是一个点集得,1能够到达3得。

2.*了**了我真是,每次最后都要多加一个换行符,你要是不加返回的不是pe是wa!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 100010;
const int maxm = 1000100;
struct *** {
	int v, w, ne, cap, u;
}ed[maxm];
bool vis[maxn];
int n, m, cnt;
int head[maxn], dis[maxn], cur[maxn];
void init() {
	cnt = 0;
	memset(head, -1, sizeof(head));
}
void add(int u, int v, int w) {
	ed[cnt].v = v; ed[cnt].w = w; ed[cnt].cap = w; ed[cnt].u = u;
	ed[cnt].ne = head[u]; head[u] = cnt++;
	ed[cnt].v = u; ed[cnt].w = w; ed[cnt].cap = w; ed[cnt].u = v;
	ed[cnt].ne = head[v]; head[v] = cnt++;
}
int bfs(int st, int en) {
	queue<int>q;
	memset(dis, 0, sizeof(dis));
	dis[st] = 1;
	q.push(st);
	while (!q.empty()) {
		int u = q.front(); q.pop();
		if (u == en)return 1;
		for (int s = head[u]; ~s; s = ed[s].ne) {
			int v = ed[s].v;
			if (dis[v] == 0 && ed[s].w > 0) {
				dis[v] = dis[u] + 1; q.push(v);
			}
		}
	}
	return dis[en] != 0;
}
int dfs(int st, int en, int flow) {
	int ret = flow, a;
	if (st == en || flow == 0)return flow;
	for (int &s = cur[st]; ~s; s = ed[s].ne) {
		int v = ed[s].v;
		if (dis[v] == dis[st] + 1 && (a = dfs(v, en, min(ret, ed[s].w)))) {
			ed[s].w -= a;
			ed[s ^ 1].w += a;
			ret -= a;
			if (!ret)break;
		}
	}
	if (ret == flow)dis[st] = 0;
	return flow - ret;
}
int dinic(int st,int en) {
	int ans = 0;
	while (bfs(st,en)) {
		for (int i = 0; i <= n + 1; i++)
			cur[i] = head[i];
		ans += dfs(st, en,inf);
	}
	return ans;
}
void find(int st) {
	queue<int>qu;
	qu.push(st);
	memset(vis, 0, sizeof(vis));
	vis[st] = 1;
	while (qu.size()) {
		int u = qu.front(); qu.pop();
		for (int s = head[u]; ~s; s = ed[s].ne) {
			if (ed[s].w > 0) {
				if (!vis[ed[s].v])qu.push(ed[s].v), vis[ed[s].v] = 1;
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	while (~scanf("%d%d", &n, &m) && n + m) {
		init();
		while (m--) {
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			add(a, b, c);
		}
		memset(vis, 0, sizeof(vis));
		dinic(1, 2);
		find(1);
		for (int s = 0; s < cnt; s++) {
			if (!ed[s].w&&vis[ed[s].u] ^ vis[ed[s].v])cout << ed[s].u << " " << ed[s].v << endl;
		}
		cout << endl;
	}
	return 0;
}

 

全部评论

相关推荐

未知的命运:重新优化一下项目吧,不然你没机会了
点赞 评论 收藏
分享
时间线:&nbsp;1.4-1.5:&nbsp;boss&nbsp;牛客&nbsp;官网&nbsp;实习僧海投了两天,&nbsp;感觉确实没啥招人的啊,&nbsp;心里凉了一半.1.6:&nbsp;中午快手约面,&nbsp;下午字节hr飞书私聊约面,&nbsp;当时想着第一次面大厂感觉三个过一个一面就已经赢了.1.7:&nbsp;下午&nbsp;3点大厂处女面,&nbsp;哈哈面试官是重邮红岩的直接保送;&nbsp;5点快手一面,&nbsp;我说这个是我的第二次大厂面试,&nbsp;面试官问要是拿到字节和快手选择哪个,&nbsp;我说昨天看了一晚上快手百分百选快手哈哈哈.&nbsp;晚上5.30字节约二面,&nbsp;快手约二面,&nbsp;小红书约一面.1.8:&nbsp;下午2点快手二面,&nbsp;聊天面体验非常好(当天电话确认入职时间);&nbsp;4点字节二面这次不是校友了,&nbsp;然后有一个CSS实现switch效果的忘记属性咋写了,&nbsp;感觉危了;&nbsp;7.30&nbsp;问字节hr是不是挂了;&nbsp;9点开始小红书一面,&nbsp;难死我了,&nbsp;但我还是笑着面完了,&nbsp;然后卸载了小红书,&nbsp;但是过了一会会小红书hr约二面,&nbsp;遂下回来了字节约三面.1.9:&nbsp;下午2点字节三面,&nbsp;依旧聊天+算法,&nbsp;自己太菜了有一个写错了,&nbsp;面完感觉又危了;&nbsp;5点面小红书20min结束(offer审批);5.30又去问字节hr是不是挂了,&nbsp;hr小姐姐说干嘛用一个句式,&nbsp;我说手写题又又又没写出来😂,&nbsp;2min后约hr面;8.30&nbsp;快手offer总结,&nbsp;自己运气好遇到了好公司好部门好面试官,&nbsp;字节剪映&nbsp;快手电商&nbsp;小红书支付的面试体验都非常好,&nbsp;不会的题会带你一步一步思考,&nbsp;流程也非常快全部都是当天推进,&nbsp;小红书是以分钟为单位推进.&nbsp;&nbsp;面经以及细节等我慢慢整理,&nbsp;&nbsp;以及保佑所有的审批不要出问题,&nbsp;我是真怕最后全过了0offer😂bg:&nbsp;重邮&nbsp;大数据&nbsp;蓝山工作室&nbsp;一段非大厂实习
独角仙梦境:这是真👻了
找实习记录
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务