codevs 1036 商务旅行
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入描述 Input Description
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
输出描述 Output Description
在输出文件中输出该商人旅行的最短时间。
样例输入 Sample Input
5
1 2
1 5
3 5
4 5
4
1
3
2
5
样例输出 Sample Output
7
数据范围及提示 Data Size & Hint
LCA
求上一个地点last到下一地点a的LCA x
距离等于
deep[last]+deep[a]-2*deep[x]。
但是我不明白的是TLE 开大数组就过了
#include <algorithm> #include <cstring> #include <cstdio> #define Max 30000 using namespace std; struct Edge { int next,to; }edge[Max*3]; struct point { int fa,size,chain,deep; }p[Max+1000]; int kk,head[Max*3],cnt,n,m,a; void qr(int &x) { x=0;int f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+(int)ch-48; ch=getchar(); } x*=f; } void add(int u,int v) { cnt++; edge[cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt; } void dfs1(int now,int fa) { int pos=kk++; p[now].fa=fa; p[now].deep=p[p[now].fa].deep+1; for(int i=head[now];i;i=edge[i].next) { if(edge[i].to==fa) continue; dfs1(edge[i].to,now); } p[now].size=kk-pos; } void dfs2(int now,int chain) { int pos=0; p[now].chain=chain; for(int i=head[now];i;i=edge[i].next) { if(p[edge[i].to].chain) continue; if(p[pos].size<p[edge[i].to].size) pos=edge[i].to; } if(pos) dfs2(pos,chain); else return; for(int i=head[now];i;i=edge[i].next) { if(edge[i].to==p[now].fa||edge[i].to==pos) continue; dfs2(edge[i].to,edge[i].to); } } int lca(int x,int y) { while(p[x].chain!=p[y].chain) { if(p[p[x].chain].deep<p[p[y].chain].deep) swap(x,y); x=p[p[x].chain].fa; } return p[x].deep<p[y].deep?x:y; } int main() { qr(n); int k=n-1; for(int a,b;k--;) { qr(a);qr(b); add(a,b); add(b,a); } dfs1(1,0); kk=0;dfs2(1,1); int v; qr(m); qr(v); m-=1; int ans=0; for(int x,last=v;m--;) { qr(v); x=lca(v,last); ans+=p[v].deep+p[last].deep-(2*p[x].deep); last=v; } printf("%d",ans); return 0; }
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。