2502: 清理雪道

2502: 清理雪道

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 719   Solved: 383
[ Submit][ Status][ Discuss]

Description

        滑雪场坐落在 FJ 省西北部的若干座山上。
从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。

Input

输入文件的第一行包含一个整数 n  (2 <= n <= 100) –  代表滑雪场的地点的数量。接下来的 n 行,描述 1~n 号地点出发的斜坡,第 i 行的第一个数为 mi  (0 <= mi < n ,后面共有 mi 个整数,由空格隔开,每个整数 aij 互不相同,代表从地点 i 下降到地点 aij 的斜坡。每个地点至少有一个斜坡与之相连。

Output

 
        输出文件的第一行是一个整数 k  –  直升飞机的最少飞行次数。

Sample Input

8
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0

Sample Output

4

HINT

Source

2011福建集训

[ Submit][ Status][ Discuss]

无源汇有下界的最小流,,,建模在老司机与小园丁那题说过啦。。。不重复了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

const int maxn = 233;
const int maxm = 2E5 + 20;
const int INF = ~0U>>1;

struct E{
	int to,cap,flow; E(){}
	E(int to,int cap,int flow): to(to),cap(cap),flow(flow){}
}edgs[maxm];

int n,s,t,S,T,sum,cnt,in[maxn],out[maxn],L[maxn],cur[maxn];

vector  v[maxn];
queue  Q;

void Add(int x,int y,int cap)
{
	v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0);
	v[y].push_back(cnt); edgs[cnt++] = E(x,0,0);
}

int Dfs(int x,int a)
{
	if (x == T) return a; int flow = 0;
	for (int &i = cur[x]; i < v[x].size(); i++)
	{
		E &e = edgs[v[x][i]];
		if (e.cap == e.flow || L[e.to] != L[x] + 1) continue;
		int f = Dfs(e.to,min(a,e.cap - e.flow));
		if (!f) continue; flow += f; e.flow += f;
		edgs[v[x][i]^1].flow -= f; a -= f;
		if (!a) return flow;
	}
	if (!flow) L[x] = -1; return flow;
}

bool BFS()
{
	for (int i = 1; i <= T; i++) L[i] = 0;
	L[S] = 1; Q.push(S);
	while (!Q.empty())
	{
		int k = Q.front(); Q.pop();
		for (int i = 0; i < v[k].size(); i++)
		{
			E e = edgs[v[k][i]];
			if (e.cap == e.flow || L[e.to]) continue;
			L[e.to] = L[k] + 1; Q.push(e.to);
		}
	}
	return L[T];
}

int Dinic()
{
	int MaxFlow = 0;
	while (BFS())
	{
		for (int i = 1; i <= T; i++) cur[i] = 0;
		MaxFlow += Dfs(S,INF);
	}
	return MaxFlow;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> n; s = n + 1; t = s + 1; S = t + 1; T = S + 1;
	for (int i = 1; i <= n; i++)
	{
		int k; scanf("%d",&k);
		while (k--)
		{
			int x; scanf("%d",&x);
			++out[i]; ++in[x]; Add(i,x,INF);
		}
	}
	for (int i = 1; i <= n; i++)
	{
		Add(s,i,INF); Add(i,t,INF);
		int du = in[i] - out[i];
		if (du > 0) Add(S,i,du),sum += du;
		else if (du < 0) Add(i,T,-du);
	}
	Dinic(); Add(t,s,INF); cout << Dinic();
	return 0;
}

你可能感兴趣的:(网络流)