问题 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”。
样例输入
1 5 3 2 1 3 2 2 4 3 5 2 3 1 4 4 5
样例输出
Not connected 6
初看此题,便注意到了这句“当然在运输线中,更不可能存在圈。 ”,也就是说,该图是森林,对于任意两点,要么没有路径,要么
存在唯一路径,所以很容易便想到了树上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");
else
printf("%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