wa2 图论

【问题描述】
山山最近开始玩一款叫做《白色相簿 2》的 Galgame。众所周知,Galgame 的剧情可以
用一棵树来表示,其中非叶节点表示选项分支,叶子表示结局,树边表示支线剧情,剧情从
树根开始向叶子方向进行。看完一段支线剧情所花的时间是一定的。
《白色相簿 2》共有 n 个选项分支或结局,有 n - 1 段支线剧情,其中根节点被编号
为 1 号。因为山山非常心急,于是他把自己的存档功能搞崩了。
山山现在只能在固定的 k 个选项前存档,每次观看剧情需要从存档处开始。他想花最少
的时间看一遍所有的剧情。 但是他现在有一个赛艇比赛要看,于是他希望你能帮他计算出
这个最少时间。


【输入格式】
输入文件名为 wa2.in。
第一行为两个正整数 n k。
接下来一行 k 个正整数 s 1 s 2 s 3 ...s k ,表示 k 个存档点,保证 1 号节点是一个
存档点。
接下来 n - 1 行,每行三个整数 u v t,表示节点 u 和 v 之间的那段支线剧情需要花费 t
的时间观看。
(保证 u 是 v 的前置剧情或选项)


【输出格式】
输出文件名为 wa2.out。
输出仅一行一个整数 ans 表示答案。


【样例输入与输出】

5 2

1 2

1 2 3

2 3 2

2 4 1

1 5 6

 

12


 

其实这题没什么难度,就是需要注意几个方面:

建双向边,dist值小心处理,叶节点的判断。

我们看了题应该可以知道如果可以保存的话,那该点之上的剧情就不需要重新计算了,

所以我们只要dfs一遍就可以得出答案。

代码:

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

#define ll long long
#define il inline
#define db double

using namespace std;

il int gi()
{
	int x=0,y=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
		{
			if(ch=='-')
				y=-1;
			ch=getchar();
		}
	while(ch>='0'&&ch<='9')
		{
			x=x*10+ch-'0';
			ch=getchar();
		}
	return x*y;
}

int head[100045],cnt;
struct edge
{
	int next,to;
	ll lon;
}e[200045];

il void add(int from,int to,ll lon)
{
	e[++cnt].next=head[from];
	e[cnt].to=to;
	e[cnt].lon=lon;
	head[from]=cnt;
}

bool vis[100045];

ll ans;

bool p[100045];

int du[100045];

void dfs(int x,ll dist)
{
	if(vis[x])
		ans+=dist,dist=0;
	int r=head[x];
	p[x]=1;
	while(r!=-1)
		{
			int now=e[r].to;
			if(!p[now])
				dfs(now,dist+e[r].lon);
			r=e[r].next;
		}
}

int main()
{
	freopen("wa2.in","r",stdin);
	freopen("wa2.out","w",stdout);
	
	memset(head,-1,sizeof(head));

	int n=gi(),k=gi();
	
	for(int i=1;i<=k;i++)
		vis[gi()]=1;

	int x,y;
	ll z;
	for(int i=1;i<n;i++)
		{
			x=gi(),y=gi();
			scanf("%lld",&z);
			du[x]++;
			du[y]++;
			add(x,y,z);
			add(y,x,z);
		}

	for(int i=1;i<=n;i++)
		if(du[i]==1)
			vis[i]=1;

	dfs(1,0);

	printf("%lld\n",ans);

	return 0;
}

 

posted @ 2017-10-16 16:08  GSHDYJZ  阅读(379)  评论(0编辑  收藏  举报