首页 > 技术文章 > 洛谷p1345---最小割的奇妙运用

lesning 2019-09-17 19:21 原文

让你去掉最少的点,使得c1和c2变得不连通,你有办法吗???

 

 

这是最小割呀!!!

网络流的最小割去掉的是边,构造边的顶点的唯一关系就好了!!!

 

 需要注意一点

 

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int Maxn = 10000 + 10;

struct Node {
	int to, cap, rev;
	Node(int a, int b, int c) :to(a), cap(b), rev(c) {}
};

vector<Node> G[Maxn];
int level[Maxn];
int iter[Maxn];
void insert(int from, int to, int cap) {
	G[from].push_back(Node(to, cap, G[to].size()));
	G[to].push_back(Node(from, 0, G[from].size() - 1));//网络流的反向边
	return;
}

void bfs(int s) {//从源点划分等级
	memset(level, -1, sizeof(level));
	queue<int> que;
	level[s] = 0;//设置初级
	que.push(s);
	while (!que.empty()) {
		int x = que.front();
		que.pop();
		for (int i = 0; i < G[x].size(); i++) {
			Node &e = G[x][i];
			if (e.cap > 0 && level[e.to] < 0) {//正边而且没有访问过
				level[e.to] = level[x] + 1;
				que.push(e.to);
			}
		}
	}

}
int dfs(int v, int t, int f) {
	if (v == t) return f;
	for (int &i = iter[v]; i < G[v].size(); i++) {
		Node &e = G[v][i];
		if (e.cap > 0 && level[v] < level[e.to]) {
			int d = dfs(e.to, t, min(f, e.cap));
			if (d > 0) {//流量存在就制造反边出来
				e.cap -= d;//走过了
				G[e.to][e.rev].cap += d;//
				return d;
			}
		}
	}
	return 0;
}
int dinic(int s, int t) {
	int flow = 0;
	while (1) {
		bfs(s);
		if (level[t] < 0) return flow;
		memset(iter, 0, sizeof(iter));
		int f;
		while ((f = dfs(s, t, INF)) > 0) {
			flow += f;
		}
	}
	return flow;
}
void inint() {
	for (int i = 0; i < Maxn; i++) {
		G[i].clear();
	}
	return;
}
int main() {

	//int T; int n;
	// int chal = dinic(1, n);
	int n, m, s, t;
	scanf("%d %d %d %d", &n, &m, &s, &t);
	s += n;                     
	for (int i = 1; i <= n; i++) {
		insert(i, i + n, 1);
	}
	int be, en;
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &be, &en);
		insert(be + n, en, INF); 
		insert(en + n, be, INF);
	}
	
	int chal = dinic(s, t);
	printf("%d\n", chal);
	return 0;
}

  

推荐阅读