交通运输线

来源:互联网 发布:linux df产生文件 编辑:程序博客网 时间:2024/04/28 02:36

问题 A: 交通运输线

题目描述

战后有很多城市被严重破坏,我们需要重建城市。然而,有些建设材料只能在某些地方产生。因此,我们必须通过城市交通,来运送这些材料的城市。由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路。当然在运输线中,更不可能存在圈。 
现在,你的任务来了。给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度。 

输入

第一行一个整数Case(Case<=10)表示测试数据组数。 
每组测试数据第一行三个整数N,M和C (2<=N<=10, 000) (0<=M<10, 000) (1<=c<=1000000)共有N个城市,现存M条边,共有C对运输需求。 
接下来M行,每行三个整数A和B,D(1<=A,B<=N,A不等于B)表示从A到B有一条直接的公路,且距离为D。 
最后C行,每行两个整数,S和T(1<=S,T<=N,S不等于T),即询问从S到T的最短路径长度。 

输出

共Case行,否存在从S到T的路径,则输出最短路径,否则输出“Not connected”。

样例输入

15 3 21 3 22 4 35 2 31 44 5

样例输出

Not connected6
    初看此题,便注意到了这句“当然在运输线中,更不可能存在圈。 ”,也就是说,该图是森林,对于任意两点,要么没有路径,要么
存在唯一路径,所以很容易便想到了树上LCA,而本人用的方法则是tarjan求公共祖先,对于在树上任意两点{u,v},设它们公共祖先
为p,dis[]表示这个点到这棵树树根的距离,于是有两点之间距离=dis[u]+dis[v]-2*dis[p],这个式子可以通过画一棵树很容易得出。
    调了一个多小时。。。哭晕,先是用边表,然而却出现RE和TL,然后改为邻接表,竟然AC了,我将两段代码都放在下面,如果有
路过的神犇可以帮我看看。
RE的代码(边表)
#include#include#define N1 10005#define N2 1000005 using namespace std;int T,n,m,c,cnt,qcnt;int f[100005],flag[N1],vis[N1],ans[N2],head[N1],next[N1],to[N1],len[N1],qhead[N2],qto[N2],qnext[N2],id[N2],dis[N1];void init(){int i;for (i=1;i<=100000;i++) f[i]=i;memset(flag,0,sizeof(flag));memset(ans,-1,sizeof(ans));memset(head,0,sizeof(head));memset(to,0,sizeof(to));memset(len,0,sizeof(len));memset(qhead,0,sizeof(qhead));memset(qto,0,sizeof(qto));memset(id,0,sizeof(id));cnt=0;qcnt=0;}void addedge(int u,int v,int p){next[++cnt]=head[u];to[cnt]=v;len[cnt]=p;head[u]=cnt;}void addqedge(int u,int v,int p){qnext[++qcnt]=qhead[u];qto[qcnt]=v;id[qcnt]=p;qhead[u]=qcnt;}int find(int x){if (f[x]==x) return x;return f[x]=find(f[x]);}void tarjan(int u){vis[u]=1;flag[u]=1;int i;for (i=head[u];i!=0;i=next[i]){int v=to[i];if (!flag[v]){dis[v]=dis[u]+len[i];tarjan(v);f[v]=u;}}for (i=qhead[u];i!=0;i=qnext[i]){int v=qto[i],x=id[i];if (flag[v] && vis[v])ans[x]=dis[u]+dis[v]-2*dis[find(v)];}}int main(){scanf("%d",&T);while (T--){init();int i;scanf("%d%d%d",&n,&m,&c);for (i=1;i<=m;i++){int u,v,p;scanf("%d%d%d",&u,&v,&p);addedge(u,v,p);addedge(v,u,p);}for (i=1;i<=c;i++){int u,v;scanf("%d%d",&u,&v);addqedge(u,v,i);addqedge(v,u,i);}for (i=1;i<=n;i++){if (!flag[i]){dis[i]=0;memset(vis,0,sizeof(vis)); tarjan(i);}}for (i=1;i<=c;i++){if (ans[i]==-1) printf("Not connected\n");elseprintf("%d\n",ans[i]);}}return 0;}
 AC的代码(邻接表)
#include#include#include#define N1 10005#define N2 100005#define N3 1000005 using namespace std;int T,n,m,c;int flag[N1],vis[N1],dis[N1],f[N2],ans[N3];struct node1{int v,len;};struct node2{int v,id;};vector  edge[N1];vector  qedge[N1];void init(){int i;for (i=1;i<=100000;i++) f[i]=i;memset(flag,0,sizeof(flag));memset(ans,-1,sizeof(ans));    for (i=1;i<=10000;i++){    edge[i].clear();    qedge[i].clear();}}int find(int x){if (f[x]==x) return x;return f[x]=find(f[x]);}void tarjan(int u){vis[u]=1;flag[u]=1;int i;for (i=0;i