POI 2000 Skiers

贪心策略、深度优先搜索

网络流模型理论上可以解决此题,把除1和n以外的每个结点都拆成两个结点,中间用一条容量为1的边连接,结点1为源,结点n为汇求最大流。无奈本题数据规模较大,最多有5000个结点,而且边数未知。

注意到题目给出的图具有特殊的性质:边是按从东到西的顺序给出的,而且所有边不相交。这样我们可以采取如下贪心策略:用深度优先搜索从结点1出发找一条尽可能靠东(或尽可能靠西)的路径,让一个运动员沿此路径滑雪,把此路径上的除起点和终点外的所有结点从图中删去,然后重复此过程。这个策略显然正确,由于所有边都不相交,每次找最靠东(或最靠西)的路径可以给后面要找的路径腾出最大的空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
 
using namespace std;
 
struct edge
{
	int v;
	edge *next;
	edge(int v,edge *next):v(v),next(next) {}
} *e[5005];
int n;
bool u[5005];
 
bool dfs(int v)
{
	if(v==n) return true;
	u[v]=true;
	for(edge *t=e[v];t;t=t->next)
		if(!u[t->v]&&dfs(t->v))
			return true;
	return false;
}
 
int main()
{
	freopen("nar.in","r",stdin);
	freopen("nar.out","w",stdout);
	scanf("%d",&n);
	int t,v,ans=0;
	for(int i=1;i<n;++i)
		for(scanf("%d",&t);t;--t)
		{
			scanf("%d",&v);
			e[i]=new edge(v,e[i]);
		}
	for(edge *p=e[1];p;p=p->next)
		if(!u[p->v]&&dfs(p->v))
			++ans;
	printf("%d\n",ans);
	return 0;
}
Posted in POI. Tags: , . No Comments »

Leave a Reply