BZOJ 2502 清理雪道/ Luogu P4843 清理雪道 (有源汇上下界最小流)

版权声明:本人版权意识薄弱,请随意转载 https://blog.csdn.net/Ike940067893/article/details/88395396

题意

有一个有向无环图,求最少的路径条数覆盖所有的边

分析

有源汇上下界最小流板题,直接放代码了,不会的看dalao博客:liu_runda
有点长,讲的很好,静心看一定能看懂

CODE

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<typename T>inline void read(T &num) {
    char ch; while((ch=getchar())<'0'||ch>'9');
    for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
}

const int MAXN = 105;
const int MAXM = 100005;
const int inf = 1e9;
int n, deg[MAXN], s, t, ss, tt, S, T;
int fir[MAXN], info[MAXN], cnt;
struct edge { int to, nxt, c; }e[MAXM];
inline void add(int u, int v, int cc) {
	e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
	e[cnt] = (edge){ u, fir[v], 0 }; fir[v] = cnt++;
}
int q[MAXN], vis[MAXN], cur, dis[MAXN];
inline bool bfs() {
	int head = 0, tail = 0;
	vis[S] = ++cur; q[tail++] = S;
	while(head < tail) {
		int u = q[head++];
		for(int i = fir[u]; ~i; i = e[i].nxt)
			if(e[i].c && vis[e[i].to] != cur)
				dis[e[i].to] = dis[u] + 1, vis[e[i].to] = cur, q[tail++] = e[i].to;
	}
	if(vis[T] == cur) memcpy(info, fir, sizeof fir);
	return vis[T] == cur;
}
int dfs(int u, int Max) {
	if(u == T) return Max;
	int flow = 0, delta;
	for(int &i = info[u]; ~i; i = e[i].nxt)
		if(e[i].c && dis[e[i].to] == dis[u] + 1 && (delta=dfs(e[i].to, min(Max-flow, e[i].c)))) {
			e[i].c -= delta, e[i^1].c += delta, flow += delta;
			if(flow == Max) return flow;
		}
	return flow;
}
inline int dinic() {
	int flow = 0, x;
	while(bfs()) {
		while((x=dfs(S, inf)))
			flow += x;
	}
	return flow;
}
inline void del(int u) {
	for(int i = fir[u]; ~i; i = e[i].nxt) e[i].c = e[i^1].c = 0;
}
int main ()
{
	memset(fir, -1, sizeof fir);
    read(n);
	for(int i = 1, j, tot; i <= n; ++i) {
		read(tot);
		while(tot--) read(j), --deg[i], ++deg[j], add(i, j, inf-1);
	}
	s = n+1, t = n+2, ss = n+3, tt = n+4;
	for(int i = 1; i <= n; ++i)
		add(s, i, inf), add(i, t, inf);
	for(int i = 1; i <= n; ++i)
		if(deg[i] < 0) add(i, tt, -deg[i]);
		else if(deg[i] > 0) add(ss, i, deg[i]);
	add(t, s, inf);
	S = ss, T = tt;
	dinic();
	int flow0 = e[cnt-1].c;
	e[cnt-1].c = e[cnt-2].c = 0;
	del(ss); del(tt);
	S = t, T = s;
	printf("%d\n", flow0-dinic());
}

U p d : Upd: 开始把" f l o w 0 d i n i c ( ) flow0-dinic() “写成了” f l o w 0 + d i n i c ( ) flow0+dinic() ",洛谷上居然 80 p t s 80pts ,数据有点水啊

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/88395396
今日推荐