【最短路好题】幻想道路
Problem C: 幻想道路
时间限制:1 second
空间限制:512 megabytes
幻想世界最近发生了几件大事,先是有快乐星球代表,再是有黑暗星球代表来到了幻想世界,他们在幻想世界
建造了一个自己的王国,并带领了一大批自己星球上的人入驻。
对于这两个新的伙伴,原来的幻想王国里的人们还不知道应该以怎样的态度去应对。但阿卡表示,不管快乐星
球与黑暗星球多么的势不两立,这都不关他们的事,他们还是要与两个星球之间都建一些道路通行。
幻想世界原来有 n 个王国,他们之间已经有了 m 条道路,这些道路都是双向的。阿卡决定为两个星球的到来
再新建 Q 条路,这样一来,有些王国就能够同时到达快乐星球与黑暗星球了。
幻想世界还有一条规定,就是每条路都有一个路霸,他会在这条路上收买路钱,但新建的 Q 条路暂时还没有
出现这种情况。每个路霸知道,所有的居民都对这两个新到来的星球十分的感兴趣,如果自己这条路不能到达黑暗
星球或者不能到达快乐星球,那么经过这条路的居民就会大大减少,就收不到多少买路钱了。另外,就算这条路能
同时到达两个星球,他能收的买路钱也跟经过这条路的快乐星球到黑暗星球的最短路有关。
这下这些路霸们着急了,他们找到了你,想让你帮忙计算一下他们关心的事。
Input
第一行一个数 n,表示幻想王国的数量。
第二行两个数 m, Q。 m 表示原来幻想王国之间边的数量, Q 表示新建的边的数量。
接下来 m 行,每行三个数 u, v, w。表示这条路连接 u, v 两个王国- 这条路的长度是 w。
保证 1 ≤ u, v ≤ n。
接下来 Q 行,每行三个数 u, v, w。表示这条路连接 u, v 两个王国- 这条路的长度是 w。
其中 u > n 或者 v > n。 n + 1 号王国表示快乐星球, n + 2 号王国表示黑暗星球。
Output
输出 m 行,每行表示一条道路。
如果这条道路不能同时到达快乐星球和黑暗星球,那么输出一行“GG” ,不包含引号.
否则输出一个数,表示经过这条道路的快乐星球到黑暗星球之间的最短路。
Example
road.in | road.out |
2 3 2 1 2 2 2 1 1 1 2 5 1 3 5 1 4 5 |
12 11 15 |
Constraints
对于 30W 的数据, n ≤ 5, m, Q ≤ 5。
对于 50W 的数据, n ≤ 50, m, Q ≤ 5。
对于 70W 的数据, n ≤ 50, m, Q ≤ 1000。
对于 100W 的数据, n, m, Q ≤ 104, 0 < w ≤ 100 。
这题的坑点其实好多啊,感觉填坑都填不过来QAQ。
题面都告诉你了,这是一道求最短路的题,那应该挺简单了,然而A掉很不容易啊QAQ。
就是跑两遍spfa,然后对于每一条边,结果等于min(dis(n + 1; x) + dis(n + 2; y),dis(n + 1; y) + dis(n + 2; x))+val(x,y)
下面来说一说我的填坑记录:
1.虽然知道是无向图,但是被样例蒙蔽了,一个城市到多个城市可以有很多种道路嘛。
2.记录连接幻想王国的边时,不能和邻接表产生一定关系。因为无向图连了两次,需要在读入时重开数组记录。
3.spfa写炸了。
4.初始化的时候注意是n+2座城市。(还有新来的快乐星球、黑暗星球)
5.最后!ans没加这条边的权值。
hhhhhhh
code
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int inf=99999; 5 int n,tot,m,Q; 6 int head[40000],dis[40000],beginn[40000],too[40000],vall[40000]; 7 bool visit[40000]; 8 pair<int,int>p1[40000]; 9 pair<int,int>p2[40000]; 10 struct node{ 11 int to,next,val; 12 }edge[40000]; 13 void add(int x,int y,int z) 14 { 15 edge[++tot].to=y; 16 edge[tot].val=z; 17 edge[tot].next=head[x]; 18 head[x]=tot; 19 } 20 void spfa(int h) 21 { 22 queue<int>q; 23 for(int i=1;i<=n+2;i++) 24 {//注意n+2 25 dis[i]=inf; 26 visit[i]=0; 27 } 28 q.push(h); 29 dis[h]=0; 30 visit[h]=1; 31 while(!q.empty()) 32 { 33 int u=q.front(); 34 q.pop(); 35 visit[u]=0; 36 for(int i=head[u];i>0;i=edge[i].next) 37 { 38 int v=edge[i].to; 39 if(dis[v]>dis[u]+edge[i].val) 40 { 41 dis[v]=dis[u]+edge[i].val; 42 if(visit[v]==0) 43 { 44 visit[v]=1; 45 q.push(v); 46 } 47 } 48 } 49 } 50 while(!q.empty()) q.pop(); 51 } 52 int main() 53 { 54 scanf("%d",&n); 55 scanf("%d%d",&m,&Q); 56 for(int i=1;i<=m;i++) 57 { 58 int u=0,v=0,w=0; 59 scanf("%d%d%d",&u,&v,&w); 60 beginn[i]=u; 61 too[i]=v; 62 vall[i]=w; 63 add(u,v,w); 64 add(v,u,w);//还是要连双向 65 } 66 for(int i=1;i<=Q;i++) 67 { 68 int u=0,v=0,w=0; 69 scanf("%d%d%d",&u,&v,&w); 70 add(u,v,w); 71 add(v,u,w); 72 } 73 spfa(n+1); 74 //cout<<dis[edge[2].to]<<endl; 75 for(int i=1;i<=m;i++) 76 {//由于是无向图,一个边连了两次,所以不能用邻接表的 77 p1[i].first=dis[beginn[i]];//dis(n+1,x) 78 p2[i].second=dis[too[i]];//dis(n+1,y) 79 } 80 spfa(n+2); 81 for(int i=1;i<=m;i++) 82 { 83 p1[i].second=dis[too[i]];//dis(n+2,y) 84 p2[i].first=dis[beginn[i]];//dis(n+2,x) 85 } 86 for(int i=1;i<=m;i++) 87 { 88 int ans=0; 89 if(p1[i].first==inf||p1[i].second==inf||p2[i].first==inf||p2[i].second==inf) 90 { 91 printf("GG\n"); 92 continue; 93 } 94 ans=min(p1[i].first+p1[i].second,p2[i].first+p2[i].second)+vall[i]; 95 //加这条边的权值!!! 96 //对于一条边 (x, y),答案就是 min(dis(n + 1; x) + dis(n + 2; y); dis(n + 1; y) + dis(n + 2; x))。 97 printf("%d\n",ans); 98 } 99 return 0; 100 }