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;
}
PEACE

浙公网安备 33010602011771号