P1629 邮递员送信
题目链接 https://www.luogu.com.cn/problem/P1629
好嘛,又没看清题,我以为只需要让dis*2就好了呢,结果就听取WA声一片了呗。
结果仔细看题目才发现这是个有向图,不是走到终点接着回头这么简单的。
既然这样,邮递员在回来的时候就是求多源点到单源点最短路的情况了,啊这,总不能n个单源到单源吧?!
(废话这范围当然不行)
反向建边:建图时将边的方向都相反,那么反向图中A点(源点)到B点(任意一点)的最短路径,就是正向图中B点(任意一点)到A点(源点)的最短路径。
画个图就明白了。
(代码写得有点儿啰嗦了,其实不用两个函数)
放AC代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 int cnt; 5 int ans; 6 bool vis[1010],fvis[1010]; 7 int head[1010],fhead[1010]; 8 long long dis[1010],fdis[1010]; 9 10 struct Edge 11 { 12 int v; 13 int w; 14 int next; 15 } edge[100010],fedge[100010]; 16 17 void add(int a,int b,int c) 18 { 19 edge[++cnt].v=b; 20 edge[cnt].w=c; 21 edge[cnt].next=head[a]; 22 head[a]=cnt; 23 fedge[cnt].v=a; 24 fedge[cnt].w=c; 25 fedge[cnt].next=fhead[b]; 26 fhead[b]=cnt; 27 } 28 29 void dijkstra() 30 { 31 for(int v=1; v<=n; v++) 32 dis[v]=INT_MAX; 33 34 int cur=1; 35 dis[cur]=0; 36 long long minn; 37 38 while(!vis[cur]) 39 { 40 vis[cur]=true; 41 for(int i=head[cur]; i!=0; i=edge[i].next) 42 { 43 if(!vis[edge[i].v] && dis[cur]+edge[i].w<dis[edge[i].v]) 44 dis[edge[i].v]=dis[cur]+edge[i].w; 45 } 46 minn=INT_MAX; 47 for(int i=1;i<=n;i++) 48 { 49 if(!vis[i] && dis[i]<minn) 50 { 51 minn=dis[i]; 52 cur=i; 53 } 54 } 55 } 56 } 57 58 void fdijkstra() 59 { 60 for(int v=1; v<=n; v++) 61 fdis[v]=INT_MAX; 62 63 int cur=1; 64 fdis[cur]=0; 65 long long minn; 66 67 while(!fvis[cur]) 68 { 69 fvis[cur]=true; 70 for(int i=fhead[cur]; i!=0; i=fedge[i].next) 71 { 72 if(!fvis[fedge[i].v] && fdis[cur]+fedge[i].w<fdis[fedge[i].v]) 73 fdis[fedge[i].v]=fdis[cur]+fedge[i].w; 74 } 75 minn=INT_MAX; 76 for(int i=1;i<=n;i++) 77 { 78 if(!fvis[i] && fdis[i]<minn) 79 { 80 minn=fdis[i]; 81 cur=i; 82 } 83 } 84 } 85 } 86 87 int main() 88 { 89 cin>>n>>m; 90 for(int e=1; e<=m; e++) 91 { 92 int a,b,c; 93 cin>>a>>b>>c; 94 add(a,b,c); 95 } 96 dijkstra(); 97 fdijkstra(); 98 for(int i=1;i<=n;i++) 99 ans+=dis[i]+fdis[i]; 100 cout<<ans; 101 return 0; 102 }