您的位置:首页 > 其它

拉力赛

2016-07-09 07:47 309 查看

拉力赛

Time Limits: 1000 ms Memory Limits: 65536 KB

Description

车展结束后,游乐园决定举办一次盛大的山道拉力赛,平平和韵韵自然也要来参加大赛。

赛场上共有n个连通的计时点,n-1条赛道(构成了一棵树)。每个计时点的高度都不相同(父结点的高度必然大于子结点),相邻计时点间由赛道相连。由于马力不够,所以韵韵的遥控车只能从高处驶向低处。而且韵韵的车跑完每条赛道都需花费一定的时间。

举办方共拟举办m个赛段的比赛,每次从第u个计时点到第v个计时点,当然其中有不少比赛韵韵的遥控车是不能参加的(因为要上坡)。平平想知道他能参加多少个赛段的比赛,并且想知道他完成这些赛段的总用时。

Input

第一行两个整数n,m。

接下来n-1行每行3个整数a、b、t。

表示韵韵的遥控车可以花t秒从第a个计时点到第b个计时点。

接下来m行每行2个整数u、v,意义如描述所示。

Output

第一行输出一个正整数,表示能参加的赛段数。

第二行输出一个正整数,表示总用时。

Sample Input

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


Sample Output

1
2


Hint

【数据规模和约定】

第一个计时点的高度是最高的;

u≠v;

对于50%的数据 n≤1000 m≤1000;

对于100%的数据 n≤10000 m≤100000;

答案小于2^64。

解题思路

于题意得,只要遥控车不向父亲节点去走,就一定符合要求。

明显LCA,再求路径的时候判断是否可行就可以了。

codes:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define fo(i,x,y) for(int i=x;i<=y;i++)
using namespace std;

int r[20001][4],first[10001],last[10001],n,m,tot=0,f[10001][17],flor[10001];
long long total,d[10001][17],data[10001][2];
bool bz[10001];

void insert(int,int,int,int);
void build(int);
void doit(int,int);

int main()
{
scanf("%d%d",&n,&m);
fo(i,1,n-1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(i,x,y,z);
insert(i+n,y,x,z);
}
build(1);
fo(j,1,16)fo(i,1,n)
{
f[i][j]=f[f[i][j-1]][j-1];
d[i][j]=d[f[i][j-1]][j-1]+d[i][j-1];
}
fo(i,1,m)
{
int x,y;
scanf("%d%d",&x,&y);
doit(x,y);
}
printf("%d\n%lld",tot,total);
}

void insert(int w,int x,int y,int z)
{
r[w][0]=x;r[w][1]=y;r[w][2]=z;r[w][3]=w;
if(first[x]==0)first[x]=w;else r[last[x]][3]=w;
last[x]=w;
}

void doit(int x,int y)
{
int s=flor[y]-flor[x];
long long v=0;
if(s<0){return;}
fo(i,0,16)if((s &(1<<i))>0)
{
v+=d[y][i];
y=f[y][i];
}
if(x==y)
{
tot++;
total+=v;
}
}

void build(int w)
{
data[1][0]=w;data[1][1]=0;
int h=0,t=1;
memset(bz,0,sizeof(bz));
bz[w]=1;
while(h<t)
{
int now=data[++h][0];
flor[now]=data[h][1];
int o=first[now];
while(1)
{
int x=r[o][1];
if(bz[x])
{
if(o==r[o][3])break;
o=r[o][3];continue;
}
bz[x]=1;
data[++t][0]=x;
data[t][1]=data[h][1]+1;
f[x][0]=now;
d[x][0]=r[o][2];
if(o==r[o][3])break;
o=r[o][3];
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: