您的位置:首页 > 其它

poj 2114 Boatherds

2014-05-26 21:23 183 查看
Boatherds
Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 1145Accepted: 373
DescriptionBoatherds Inc. is a sailing company operating in the country of Trabantustan and offering boat trips on Trabantian rivers. All the rivers originate somewhere in the mountains and on their way down to the lowlands they gradually join and finally the single resulting river flows to the sea. Moreover, the Trabantian villages are exactly at the rivers' springs, junctions and at the mouth of the largest river. Please note that more than 2 rivers can join at a junction. However, the rivers always form a tree (with villages as vertices). The pricing policy of the Boatherds is very simple: each segment of each river between two villages is assigned a price (the price is same in both directions), so if a tourist requests a journey between any two villages, the ticket office clerks just add the prices of the segments along the only path between the villages. One day, a very strange tourist appeared. She told the clerks that she returns to her country on the next day and she wants to spend all the remaining money on a boat trip, so they should find a route with exactly this cost. Being just poor (ahem) businessmen, they have asked the Abacus Calculator Makers for help. You are given a description of the river network with costs of river segments and a sequence of integers x1,..., xk. For each xi, you should determine if there is a pair of cities (a, b) in the river network such that the cost of the trip between a and b is exactly xi. InputThe input consists of several instances. Each instance is described by (in the following order): A single line containing a single integer: the number of villages N (1 <= N <= 10 000). N lines describing the villages. The i-th of these lines (1 <= i <= N) describes the village with number i. It contains space separated integers d1, c1, d2, c2, , dki, cki, 0. The dj's are numbers of villages from which the rivers flow directly to the village i (with no other villages in between), each cj is the price of the journey between villages i and dj. Moreover, 2 <= dj <= N and 0 <= cj <= 1 000. Village 1 always corresponds to the mouth of the largest river, therefore no di can ever be equal to 1. M <= 100 lines describing the queries. The i-th of these lines corresponds to the i-th query and contains a single integer xi (1 <= xi <= 10 000 000). The instance is finished by a single line containing the number 0.The whole input is ended by a single line containing the number 0. OutputFor each instance you should produce a sequence of M lines (where M is the number of queries in the particular instance). The i-th of these lines contains the word "AYE" if there exists a pair of cities in the river network which is connected by a path of cost xi, or the word "NAY" otherwise. Output for each instance must be followed by a single line containing just the dot character. Sample Input
6
2 5 3 7 4 1 0
0
5 2 6 3 0
0
0
0
1
8
13
14
0
0
Sample Output
AYE
AYE
NAY
AYE
.
树分治的论文题,和Poj1741一样,只是统计点对时,有一些差别。
对于某个没有统计的点,我们把和它之间有路径,并且没有统计过的点提出来,构成一棵树,先找出重心,以重心为根,计算出每个点到根的距离,统计出所有相距为k的点对数,再减去重心的每个相邻点的儿子孙子们中距离相加=k的对数,然后递归刚才的步骤到重心的儿子们。
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define rep(i,s,t) for(int i=s;i<t;i++)#define clr(a,v) memset(a,v,sizeof a)#define N 10005struct Edge{    int v,w,next;}edge[N*2];int head,e,n;int son;int d,cnt;int x,y,root,k,Maxsize,all;bool vis;inline void addEdge(int u,int v,int w){    edge[e].v=v;    edge[e].w=w;    edge[e].next=head[u];    head[u]=e++;}inline void In(){    clr(head,-1);e=0;    rep(i,1,n+1){        while(scanf("%d",&x),x){            scanf("%d",&y);            addEdge(i,x,y);            addEdge(x,i,y);        }    }}inline void dfs_Size(int now,int pre){    all++;    for(int i=head[now];i!=-1;i=edge[i].next){        if(!vis[edge[i].v] && edge[i].v!=pre){            dfs_Size(edge[i].v,now);        }    }}inline void dfs_Root(int now,int pre){    int Max=0;    son[now]=0;    for(int i=head[now];i!=-1;i=edge[i].next){        if(!vis[edge[i].v] && edge[i].v!=pre){            dfs_Root(edge[i].v,now);            son[now]+=son[edge[i].v]+1;            if(Max<son[edge[i].v]+1){                Max=son[edge[i].v]+1;            }        }    }    Max=max(Max,all-son[now]-1);    if(Max<Maxsize){        root=now;        Maxsize=Max;    }}inline void dfs_Dis(int now,int pre,int dis){    d[cnt++]=dis;    for(int i=head[now];i!=-1;i=edge[i].next){        int nxt=edge[i].v,w=edge[i].w;        if(nxt!=pre && !vis[nxt]){            dfs_Dis(nxt,now,dis+w);        }    }}inline int Cal(int now,int dis){    cnt=0;    dfs_Dis(now,-1,dis);    sort(d,d+cnt);    int ans=0;    rep(i,0,cnt){        int nxt=k-d[i];        ans+=upper_bound(d+i+1,d+cnt,nxt)-lower_bound(d+i+1,d+cnt,nxt);    }    return ans;}inline int Work(int now){    root=now;all=0;Maxsize=n+10;    dfs_Size(now,-1);    dfs_Root(now,-1);    vis[root]=1;    int ans=Cal(root,0);    for(int i=head[root];i!=-1;i=edge[i].next){        int nxt=edge[i].v,w=edge[i].w;        if(!vis[nxt]){            ans-=Cal(nxt,w);            ans+=Work(nxt);        }    }    return ans;}int main(){    while(scanf("%d",&n),n){        In();        while(scanf("%d",&k),k){            clr(vis,0);            if(Work(1)>0)   puts("AYE");            else    puts("NAY");        }        puts(".");    }    return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: