【BZOJ】2929: [Poi1999]洞穴攀行(最大流)

http://www.lydsy.com/JudgeOnline/problem.php?id=2929

题意描述不清。。搞得我wa了一发。。

应该是,有1和n的点的边容量都为1,其余随便。。。

然后是裸题。。

#include <cstdio>

#include <cstring>

#include <cmath>

#include <string>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

using namespace std;

typedef long long ll;

#define rep(i, n) for(int i=0; i<(n); ++i)

#define for1(i,a,n) for(int i=(a);i<=(n);++i)

#define for2(i,a,n) for(int i=(a);i<(n);++i)

#define for3(i,a,n) for(int i=(a);i>=(n);--i)

#define for4(i,a,n) for(int i=(a);i>(n);--i)

#define CC(i,a) memset(i,a,sizeof(i))

#define read(a) a=getint()

#define print(a) printf("%d", a)

#define dbg(x) cout << (#x) << " = " << (x) << endl

#define error(x) (!(x)?puts("error"):0)

#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)

inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }



const int N=415, oo=~0u>>1;

int ihead[N], cnt=1;

struct dat { int next, to, from, cap; }e[N*N*2];

void add(int u, int v, int c) {

	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].from=u; e[cnt].to=v; e[cnt].cap=c;

	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].from=v; e[cnt].to=u; e[cnt].cap=0;

}

int p[N], d[N], gap[N], cur[N];

int isap(int s, int t, int n) {

	for1(i, 0, n) p[i]=0, d[i]=0, gap[i]=0, cur[i]=ihead[i];

	gap[0]=n; int ret=0, f, u=s, i;

	while(d[s]<n) {

		for(i=cur[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1==d[u]) break;

		if(i) {

			p[e[i].to]=cur[u]=i; u=e[i].to;

			if(u==t) {

				for(f=oo; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);

				for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;

				ret+=f;

			}

		}

		else {

			if(!(--gap[d[u]])) break;

			d[u]=n; cur[u]=ihead[u];

			for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1<d[u]) d[u]=d[e[i].to]+1;

			++gap[d[u]];

			if(u!=s) u=e[p[u]].from;

		}

	}

	return ret;

}



int n;

int main() {

	read(n);

	for1(i, 1, n-1) {

		int k=getint();

		while(k--) {

			int t=getint();

			if(i==1 || t==n) add(i, t, 1);

			else add(i, t, oo);

		}

	}

	printf("%d\n", isap(1, n, n));

	return 0;

}

  

 


 

 

Description

一队洞穴学者在Byte Mountain的Grate Cave里组织了一次训练。训练中,每一位洞穴学者要从最高的一个室到达最底下的一个室。他们只能向下走。一条路上每一个连续的室都要比它的前一个低。此外,每一个洞穴学者都要从最高的室出发,沿不同的路走到最低的室。问:可以有多少个人同时参加训练?
 
任务:
写一个程序:
l        读入对洞穴的描述。
l         计算可以同时参加训练的人数。
l         将结果输出。
 

Input

 
第一行有一个整数n(2<=n<=200),等于洞穴中室的个数。用1~n给室标号,号码越大就在越下面。最高的室记为1,最低的室记为n。以下的n-1行是对通道的描述。第I+1行包含了与第I个室有通道的室(只有比标号比I大的室)。这一行中的第一个数是m,0<=m<=(n-i+1),表示被描述的通道的个数。接着的m个数字是与第I个室有通道的室的编号。
 

Output

 
输出一个整数。它等于可以同时参加训练的洞穴学者的最大人数。
 

Sample Input

12
4 3 4 2 5
1 8
2 9 7
2 6 11
1 8
2 9 10
2 10 11
1 12
2 10 12
1 12
1 12

Sample Output

3

HINT

 

Source

 

 

你可能感兴趣的:(poi)