POJ 2114 Boatherds
2016-05-10 22:37
260 查看
Description
Boatherds 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.
Input
The 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.
Output
For 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
Sample Output
简单的树分治,统计长度为k的路径是否存在。
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const int INF=0x7FFFFFFF;
int n,m,x,y;
int p[maxn],t;
bool flag[100];
struct Tree
{
int ft[maxn],nt[maxn],u[maxn],v[maxn],sz;
int vis[maxn],mx[maxn],ct[maxn];
int d[maxn],tot;
map<int,int> M;
void clear(int n)
{
mx[sz=0]=INF;
for (int i=1;i<=n;i++) ft[i]=-1,vis[i]=0;
}
void AddEdge(int x,int y,int z)
{
u[sz]=y; v[sz]=z; nt[sz]=ft[x]; ft[x]=sz++;
u[sz]=x; v[sz]=z; nt[sz]=ft[y]; ft[y]=sz++;
}
int dfs(int x,int fa,int sum)
{
int y=mx[x]=(ct[x]=1)-1;
for (int i=ft[x];i!=-1;i=nt[i])
{
if (vis[u[i]]||u[i]==fa) continue;
int z=dfs(u[i],x,sum);
ct[x]+=ct[u[i]];
mx[x]=max(mx[x],ct[u[i]]);
y=mx[y]<mx[z]?y:z;
}
mx[x]=max(mx[x],sum-ct[x]);
return mx[x]<mx[y]?x:y;
}
void get(int x,int fa,int len)
{
d[tot++]=len;
for (int i=ft[x];i!=-1;i=nt[i])
{
if (vis[u[i]]||u[i]==fa) continue;
get(u[i],x,len+v[i]);
}
}
void find(int x)
{
M.clear(); M[0]=1;
for (int i=ft[x];i!=-1;i=nt[i])
{
if (vis[u[i]]) continue;
tot=0;
get(u[i],x,v[i]);
for (int j=0;j<tot;j++)
{
for (int k=0;k<t;k++)
{
if (flag[k]) continue;
if (M.count(p[k]-d[j])) flag[k]=true;
}
}
for (int j=0;j<tot;j++) M[d[j]]=1;
}
}
void work(int x,int sum)
{
int y=dfs(x,-1,sum);
find(y); vis[y]=1;
for (int i=ft[y];i!=-1;i=nt[i])
{
if (vis[u[i]]) continue;
work(u[i],ct[u[i]]>ct[y]?sum-ct[y]:ct[u[i]]);
}
vis[y]=0;
}
}solve;
int main()
{
while (~scanf("%d",&n),n)
{
solve.clear(n);
for (int i=1;i<=n;i++)
{
while (scanf("%d",&x),x)
{
scanf("%d",&y);
solve.AddEdge(i,x,y);
}
}
t=0;
while (~scanf("%d",&p[t]),p[t]) flag[t++]=false;
solve.work(1,n);
for (int i=0;i<t;i++) printf("%s\n",flag[i]?"AYE":"NAY");
printf(".\n");
}
return 0;
}
Boatherds 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.
Input
The 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.
Output
For 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.
简单的树分治,统计长度为k的路径是否存在。
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const int INF=0x7FFFFFFF;
int n,m,x,y;
int p[maxn],t;
bool flag[100];
struct Tree
{
int ft[maxn],nt[maxn],u[maxn],v[maxn],sz;
int vis[maxn],mx[maxn],ct[maxn];
int d[maxn],tot;
map<int,int> M;
void clear(int n)
{
mx[sz=0]=INF;
for (int i=1;i<=n;i++) ft[i]=-1,vis[i]=0;
}
void AddEdge(int x,int y,int z)
{
u[sz]=y; v[sz]=z; nt[sz]=ft[x]; ft[x]=sz++;
u[sz]=x; v[sz]=z; nt[sz]=ft[y]; ft[y]=sz++;
}
int dfs(int x,int fa,int sum)
{
int y=mx[x]=(ct[x]=1)-1;
for (int i=ft[x];i!=-1;i=nt[i])
{
if (vis[u[i]]||u[i]==fa) continue;
int z=dfs(u[i],x,sum);
ct[x]+=ct[u[i]];
mx[x]=max(mx[x],ct[u[i]]);
y=mx[y]<mx[z]?y:z;
}
mx[x]=max(mx[x],sum-ct[x]);
return mx[x]<mx[y]?x:y;
}
void get(int x,int fa,int len)
{
d[tot++]=len;
for (int i=ft[x];i!=-1;i=nt[i])
{
if (vis[u[i]]||u[i]==fa) continue;
get(u[i],x,len+v[i]);
}
}
void find(int x)
{
M.clear(); M[0]=1;
for (int i=ft[x];i!=-1;i=nt[i])
{
if (vis[u[i]]) continue;
tot=0;
get(u[i],x,v[i]);
for (int j=0;j<tot;j++)
{
for (int k=0;k<t;k++)
{
if (flag[k]) continue;
if (M.count(p[k]-d[j])) flag[k]=true;
}
}
for (int j=0;j<tot;j++) M[d[j]]=1;
}
}
void work(int x,int sum)
{
int y=dfs(x,-1,sum);
find(y); vis[y]=1;
for (int i=ft[y];i!=-1;i=nt[i])
{
if (vis[u[i]]) continue;
work(u[i],ct[u[i]]>ct[y]?sum-ct[y]:ct[u[i]]);
}
vis[y]=0;
}
}solve;
int main()
{
while (~scanf("%d",&n),n)
{
solve.clear(n);
for (int i=1;i<=n;i++)
{
while (scanf("%d",&x),x)
{
scanf("%d",&y);
solve.AddEdge(i,x,y);
}
}
t=0;
while (~scanf("%d",&p[t]),p[t]) flag[t++]=false;
solve.work(1,n);
for (int i=0;i<t;i++) printf("%s\n",flag[i]?"AYE":"NAY");
printf(".\n");
}
return 0;
}
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2159 Ancient Cipher
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- POJ1050 最大子矩阵和
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)