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
lca裸题
最短距离为每两个相邻的点到lca的距离。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 300000 using namespace std; bool vis[N]; int n,m,x,y,tot,lca,ans; int a[N],fa[N],deep[N],size[N],top[N],head[N]; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } struct Edge { int from,to,next; }edge[N]; int add(int x,int y) { tot++; edge[tot].to=y; edge[tot].next=head[x]; head[x]=tot; } int dfs(int x) { size[x]=1;vis[x]=true; deep[x]=deep[fa[x]]+1; for(int i=head[x];i;i=edge[i].next) { int to=edge[i].to; if(fa[x]!=to&&!vis[to]) { fa[to]=x; dfs(to); size[x]+=size[to]; } } } int dfs1(int x) { int t=0; vis[x]=true; if(!top[x]) top[x]=x; for(int i=head[x];i;i=edge[i].next) { int to=edge[i].to; if(fa[x]!=to&&size[to]>size[t]) t=to; } if(t&&!vis[t]) { top[t]=top[x]; dfs1(t); } for(int i=head[x];i;i=edge[i].next) { int to=edge[i].to; if(fa[x]!=to&&to!=t&&!vis[to]) dfs1(to); } } int LCA(int x,int y) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); x=fa[x]; } if(deep[x]>deep[y]) swap(x,y); return x; } int main() { n=read();a[0]=1; for(int i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x); dfs(1);memset(vis,0,sizeof(vis)); dfs1(1);m=read();//a[1]=read(); for(int i=1;i<=m;i++) { a[i]=read(); lca=LCA(a[i-1],a[i]); ans+=deep[a[i-1]]+deep[a[i]]-2*deep[lca]; //printf("%d %d\n",lca,ans); } printf("%d",ans); return 0; }
时间: 2024-11-08 22:23:57