题目描述 Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
枯燥无味的直接发代码的话,我自己都看不下去,所以我决定讲讲做法,实在做不出来的,再抄我下面的代码吧;
首先我们应该先知道怎么解,路线如下:
1-->3-->2-->5 而n可以达到30000,如果每个点都用spfa求最短距离然后再累加的话,肯定超时
因为图中没有存在环,所以肯定两点之间只存在一条路线,用lca做就妥妥过了(如果可以也能用线段树过,会的来教一下我)
也就是说,只要求出1->1(求1->1是怕数据有开始第一个点不是到达1的),1->3,3->2,2->5的最近公共祖先,然后求每对顶点都最近公共祖先的距离和即可算出;
如果听不大懂没关系,我下面稍微模拟一下样例吧
1
/ \
2 5
/ \
3 4
图在上面
1.先用bfs算一次顶点1到各个顶点的距离,用dis数组表示:
1 2 3 4 5
dis 0 1 2 2 1
求这个距离的用处,例如:2和5的最近公共祖先为1,而2到5的距离就是dis[2]-dis[1]+dis[5]-dis[1]=(dis[2]+dis[5])-2*dis[1]=2,就是2到公共祖先的距离加上5到公共祖先的距离
2.然后lca的做法自己百度吧,算出1--1,1--3,3--2,2--5的公共祖先,刚好都是1(,,,,)然后算出(dis[1]+dis[1])-2*dis[1]+(dis[1]+dis[3])-2*dis[1]+(dis[3]+dis[2])-2*dis[1]+(dis[2]+dis[5])-2*dis[1] 就是答案了
最后,还有不懂的联系[email protected],也欢迎来纠正错误,更欢迎希望神犇来带我飞
codevs上的同个题解也是我写的,就不要怀疑我抄袭了:)
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <queue> 5 #include <cstring> 6 using namespace std; 7 const int _maxn=30010; 8 vector<int> a[_maxn]; 9 vector<int> t[_maxn]; 10 queue<int> que; 11 int dis[_maxn],n,m,f[_maxn]; 12 bool vis[_maxn]; 13 struct question 14 { 15 int u,v,ans; 16 }b[_maxn]; 17 void read() 18 { 19 int i,x,y; 20 scanf("%d",&n); 21 for(i=1;i<n;i++) 22 { 23 f[i]=i; 24 scanf("%d%d",&x,&y); 25 a[x].push_back(y); 26 a[y].push_back(x); 27 } 28 f[n]=n; 29 scanf("%d",&m); 30 b[1].u=1; 31 for(i=1;i<=m;i++) 32 { 33 scanf("%d",&x); 34 b[i].v=x; 35 t[x].push_back(i); 36 if(i+1<=m) 37 { 38 b[i+1].u=x; 39 t[x].push_back(i+1); 40 } 41 } 42 } 43 int find(int x) 44 { 45 return f[x]==x?x:find(f[x]); 46 } 47 void lca(int x,int fa) 48 { 49 int l=a[x].size(),i,to; 50 for(i=0;i<l;i++) 51 { 52 to=a[x][i]; 53 if(to==fa) 54 continue; 55 lca(to,x); 56 f[to]=x; 57 vis[to]=true; 58 } 59 l=t[x].size(); 60 int xx,yy,zz; 61 for(i=0;i<l;i++) 62 { 63 to=t[x][i]; 64 xx=b[to].u; 65 yy=b[to].v; 66 if(xx==yy) 67 b[to].ans=xx; 68 if(xx!=x && yy==x && vis[xx]) 69 b[to].ans=find(xx); 70 if(xx==x && yy!=x && vis[yy]) 71 b[to].ans=find(yy); 72 } 73 } 74 void bfs() 75 { 76 memset(vis,false,sizeof(vis)); 77 que.push(1); 78 vis[1]=true; 79 dis[1]=0; 80 int i,l,from,to; 81 while(!que.empty()) 82 { 83 from=que.front(); 84 que.pop(); 85 l=a[from].size(); 86 for(i=0;i<l;i++) 87 { 88 to=a[from][i]; 89 if(!vis[to]) 90 { 91 dis[to]=dis[from]+1; 92 vis[to]=true; 93 que.push(to); 94 } 95 } 96 } 97 } 98 int clac_ans() 99 { 100 int x,y,z,sum=0; 101 for(int i=1;i<=m;i++) 102 { 103 x=b[i].u; 104 y=b[i].v; 105 z=b[i].ans; 106 sum=sum+(dis[x]+dis[y])-(dis[z]<<1); 107 } 108 return sum; 109 } 110 void work() 111 { 112 bfs(); 113 memset(vis,false,sizeof(vis)); 114 lca(1,1); 115 printf("%d\n",clac_ans()); 116 } 117 int main() 118 { 119 read(); 120 work(); 121 return 0; 122 }
codevs1036