现在的位置: 首页 > 综合 > 正文

模拟题 宠物之战(时间限制:1s;空间限制:256MB)

2018年04月24日 ⁄ 综合 ⁄ 共 2082字 ⁄ 字号 评论关闭

问题描述

众所周知,moreD的宠物已经被moreD奴役得体无完肤。这只宠物实在忍无可忍,把自己每天走魔法树的经历告诉了自己的宠物。同时他还说明了自己爬树是多么地慢,以至于moreD每天都残酷地训练他爬树。
幸运的是moreD的宠物的宠物不是moreD的宠物,moreD的宠物深知”宠物是用来宠的而不是用来奴役的”这一点,所以moreD的宠物对待自己的宠物很有爱。所以moreD的宠物与其宠物商量着要推翻moreD的暴政,方法是把moreD告上法庭,就以自己每天被迫爬树来做证据。
由于魔法树是树,训练树当然也是树啦。
moreD的训练有着GX的文化,每天moreD会把自己的宠物通灵到树的一个端点上,这个通灵点可能与之前的通灵点相同。然后moreD命令他的宠物从这个点开始走,让这只宠物随便访问自己该天之前没有访问过的节点,一直走到该天无路可走,训练才会结束,宠物才可以休息。
moreD的宠物每天都会在这棵树上训练,幸运的是他每天走过的训练路径都不同,直到若干天后,所有可能的训练路径都被走遍了。
你,作为moreD宠物的宠物,一只被moreD的宠物宠着的宠物,当然想帮moreD的宠物算出他总共走过的路径长度啦。

输入格式

第一行包含两个正整数N,M,表示树的点数与边数。
接下来M行,每行三个正整数表示Li,bi,ci分别表示树上有一条长度为Li的连接bi,ci两个结点的边。

输出格式

仅一行表示答案。

输入样例

5 4
1 2 1
1 3 1
2 4 2
2 5 2

输出样例

37

数据范围

对于30%的数据N≤300
对于70%的数据N≤3,000
对于100%的数据对于所有输入的整数均不大于100,000,输入的树保证连通,无重边,无自环。

样例解释

可能的训练路径有(1-2-4),(1-2-5),(1-3),(2-4),(2-5),(2-1-3),(3-1-2-4),(3-1-2-5)
(4-2-5),(4-2-1-3),(5-2-4),(5-2-1-3)
长度依次为3,3,1,2,2,2,4,4,4,4,4,4。和为37.

题解

怪怪的题目,其实就是要求出所有“两个端点至少有一个为叶子节点”的路径长度和。只要考虑每个边对答案的贡献次数即可。注意:long long强转要放在每个变量前,否则是乘完再转。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define ll long long
#define MAXN 100002
using namespace std;
int n,m,zz,head[MAXN],con[MAXN],root;
struct bian{int frm,to,nx,v;} e[MAXN*2];
ll son[MAXN],leaf[MAXN],fa[MAXN];
ll ans;
//------------------------------------------------------------------------------
void insert(int x,int y,int z)
{
	zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz;
	zz++; e[zz].to=x; e[zz].v=z; e[zz].nx=head[y]; head[y]=zz;
}
void init()
{
	scanf("%d%d",&n,&m);
	int i,x,y,z;
	for(i=1;i<=m;i++)
	   {scanf("%d%d%d",&z,&x,&y);
	    insert(x,y,z);
	    //con[x]++; con[y]++;
	   }
	//for(i=1;i<=n;i++)
	   //{if(con[i]>1) {root=i; break;}}
}
void dfs(int x)
{
	int tag=0,i,p;
	son[x]=1;
	for(i=head[x];i;i=e[i].nx)
	   {p=e[i].to;
		if(p==fa[x]) continue;
		tag=1;
		fa[p]=x; dfs(p);
		son[x]+=son[p]; leaf[x]+=leaf[p];
	   }
	if(!tag) leaf[x]=1;
}
void dp(int x)
{
	int i,p;
	for(i=head[x];i;i=e[i].nx)
	   {p=e[i].to;
	    if(p==fa[x]) continue;
	    ans+=(ll) (leaf[p]*(son[1]-son[p])+(leaf[1]-leaf[p])*son[p])*e[i].v;
	    dp(p);
	   }
}
int main()
{
	freopen("senso.in","r",stdin);
	freopen("senso.out","w",stdout);
	init(); dfs(1);
	//for(int i=1;i<=n;i++) printf("%d: %d %d\n",i,son[i],leaf[i]);
	dp(1);
	printf("%I64d\n",ans);
	return 0;
}

抱歉!评论已关闭.