【问题描述】
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
【输入】
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。
下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。
在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
【输出】
在输出文件中输出该商人旅行的最短时间。
【算法分析】
直接使用Tarjan离线LCA算法可以通过所有数据。
【程序代码】
1 #include2 #include 3 using namespace std; 4 int g[30010][510],dis[30010],num[30010],point[30010],n,m,ans=0; 5 int fa[30010],que[30010][3]; 6 bool bo[30010]; 7 void buildtree(int u){ 8 for (int i=1;i<=num[u];i++) 9 if (!bo[g[u][i]]){10 bo[g[u][i]]=true;11 dis[g[u][i]]=dis[u]+1;12 buildtree(g[u][i]);13 }14 }15 int find(int u){16 return fa[u]==u?u:fa[u]=find(fa[u]);17 }18 void tarjan(int u){19 bo[u]=true;20 for (int i=1;i<=que[u][0];i++)21 if (bo[que[u][i]]) ans+=dis[u]+dis[que[u][i]]-2*dis[find(que[u][i])];22 for (int i=1;i<=num[u];i++)23 if (!bo[g[u][i]]){24 tarjan(g[u][i]);25 fa[g[u][i]]=u;26 }27 }28 int main(){29 memset(g,0,sizeof(g));30 memset(num,0,sizeof(num));31 memset(dis,0,sizeof(dis));32 memset(point,0,sizeof(point));33 memset(bo,0,sizeof(bo));34 memset(que,0,sizeof(que));35 scanf("%d",&n);36 for (int i=1;i<=n;i++) fa[i]=i;37 for (int i=1;i
声明:本文章系博主原创,未经允许请勿转载。