uestc 1717 Journey
来源:互联网 发布:ubuntu如何切换输入法 编辑:程序博客网 时间:2024/06/05 16:24
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <set>#include <vector>using namespace std;const int N=100009;int n,m;int a,b,c,x,y;int len[N];int get[N];int vis[N],fa[N];vector<pair<int,int> > v[N],need[N];void dfs(int x,int f,int L)//处理出每个点到根的距离{ vis[x]=1; len[x]=L; for(int i=0;i<v[x].size();i++) { int y=v[x][i].first; if(y==f)continue; dfs(y,x,L+v[x][i].second); fa[y]=x; }}void dfs2(int x,int f,int id)//vis[x]=id表示节点x对应环上的点id{ vis[x]=id; for(int i=0;i<v[x].size();i++) { int y=v[x][i].first; if(y==f)continue; dfs2(y,x,id); }}void init(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { v[i].clear(); fa[i]=i; vis[i]=0; } for(int i=1;i<=n-1;i++) { scanf("%d%d%d",&a,&b,&c); v[a].push_back(make_pair(b,c)); v[b].push_back(make_pair(a,c)); } scanf("%d%d%d",&a,&b,&c); dfs(b,-1,0);//以b为根建树 fa[b]=-1; if(c>=len[a])//如果加入的边比原先b-a的距离大,答案全为零 { for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); puts("0"); } } else { int x=a; int id=3; do //由a遍历到b,将非环上的点对应成环上的点 { vis[x]=2; for(int i=0;i<v[x].size();i++) { int y=v[x][i].first; if(y==fa[x]||vis[y]==2)continue; dfs2(y,x,id); } get[id]=x;//get[id]=x表示vis[y]=id的点都对应点x id++; x=fa[x]; }while(x!=-1); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(vis[x]!=2) x=get[vis[x]];//如果不是环上的点,找到对应点 if(vis[y]!=2) y=get[vis[y]]; if(len[y]<len[x]) swap(x,y); int tmp1=len[y]-len[x]; int tmp2=len[x]+c+len[a]-len[y];//比较绕新加入的边是否可以减少距离 if(tmp2<tmp1) { printf("%d\n",tmp1-tmp2); } else { puts("0"); } } }}int main(){ int T; scanf("%d",&T); for(int ii=1;ii<=T;ii++) { printf("Case #%d:\n",ii); init(); }return 0;}