【luogu1629】快递员送信 [spfa]
是该好好巩固一下QAQ
刷水题使我快乐
论两信竞学生如何讨论一道黄题纠结半个小时
正反各跑一遍spfa 用1次SPFA找各个点到点1的最短路,然后开一个反向图,再用SPFA搜一下点1到反向图各个点的最短路,反向图中点1到各个点的最短路就是普通图中各个点到点1的最短路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000+5,inf=1e9; 4 int n,m,ans=0; 5 inline int rd() 6 { 7 int x=0,w=0;char ch=0; 8 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 9 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 10 return w?-x:x; 11 } 12 int head[N],head1[N],cnt=0,cnt1=0; 13 struct edge 14 { 15 int v,nxt,w; 16 }e[N*100],e1[N*100]; 17 void add(int u,int v,int w) 18 { 19 e[++cnt].v=v; 20 e[cnt].w=w; 21 e[cnt].nxt=head[u]; 22 head[u]=cnt; 23 } 24 void add1(int u,int v,int w) 25 { 26 e1[++cnt1].v=v; 27 e1[cnt1].w=w; 28 e1[cnt1].nxt=head1[u]; 29 head1[u]=cnt1; 30 } 31 32 int vis[N],dis[N],dis1[N]; 33 void spfa() 34 { 35 memset(vis,0,sizeof(vis)); 36 for(int i=0;i<=n;i++) dis[i]=inf; 37 deque<int> q; 38 q.push_back(1); 39 vis[1]=1,dis[1]=0; 40 while(!q.empty()) 41 { 42 int u=q.front(); 43 q.pop_front();vis[u]=0; 44 for(int i=head[u];i;i=e[i].nxt) 45 { 46 int v=e[i].v,w=e[i].w; 47 if(dis[v]>dis[u]+w) 48 { 49 dis[v]=dis[u]+w; 50 if(!vis[v]) 51 { 52 if(!q.empty()&&dis[v]<=dis[q.front()]) q.push_front(v); 53 else q.push_back(v); 54 vis[v]=1; 55 } 56 } 57 } 58 } 59 } 60 void spfa1() 61 { 62 memset(vis,0,sizeof(vis)); 63 for(int i=0;i<=n;i++) dis1[i]=inf; 64 deque<int> q1; 65 q1.push_back(1); 66 vis[1]=1,dis1[1]=0; 67 while(!q1.empty()) 68 { 69 int u=q1.front(); 70 q1.pop_front();vis[u]=0; 71 for(int i=head1[u];i;i=e1[i].nxt) 72 { 73 int v=e1[i].v,w=e1[i].w; 74 if(dis1[v]>dis1[u]+w) 75 { 76 dis1[v]=dis1[u]+w; 77 if(!vis[v]) 78 { 79 if(!q1.empty()&&dis1[v]<=dis1[q1.front()]) 80 q1.push_front(v); 81 else 82 q1.push_back(v); 83 vis[v]=1; 84 } 85 } 86 } 87 } 88 } 89 90 int main() 91 { 92 memset(head,0,sizeof(head)); 93 memset(head1,0,sizeof(head1)); 94 n=rd(),m=rd(); 95 for(int i=1;i<=m;i++) 96 { 97 int u=rd(),v=rd(),w=rd(); 98 add(u,v,w);add1(v,u,w); 99 } 100 spfa();spfa1(); 101 for(int i=1;i<=n;i++) 102 ans+=dis[i]+dis1[i]; 103 printf("%d",ans); 104 }
还有一个完全差不多一样的题:华山论剑 但是求的 最短路径(一个来回)中最长的一条的长度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1010; 4 const int maxm=100010; 5 int n,m,s,cnt=0,cnt1=0; 6 int head[maxn],head1[maxn],dis[maxn],vis[maxn],dis1[maxn]; 7 8 struct edge 9 { 10 int u,w,v,next; 11 }e[maxm],e1[maxm]; 12 13 void add(int u,int v,int w) 14 { 15 cnt++; 16 e[cnt].u=u; 17 e[cnt].v=v; 18 e[cnt].w=w; 19 e[cnt].next=head[u]; 20 head[u]=cnt; 21 } 22 23 void add1(int u,int v,int w) 24 { 25 cnt1++; 26 e1[cnt1].u=u; 27 e1[cnt1].v=v; 28 e1[cnt1].w=w; 29 e1[cnt1].next=head1[u]; 30 head1[u]=cnt1; 31 } 32 queue<int> q; 33 void spfa() 34 { 35 q.push(s); 36 dis[s]=0;vis[s]=1; 37 while(!q.empty()) 38 { 39 int u=q.front(); 40 q.pop();vis[u]=0; 41 for(int i=head[u];i!=-1;i=e[i].next) 42 { 43 int v=e[i].v,w=e[i].w; 44 if(dis[v]>dis[u]+w) 45 { 46 dis[v]=dis[u]+w; 47 if(vis[v]==0) 48 { 49 q.push(v); 50 vis[v]=1; 51 } 52 } 53 } 54 } 55 } 56 57 void spfa1() 58 { 59 q.push(s); 60 dis1[s]=0;vis[s]=1; 61 while(!q.empty()) 62 { 63 int u=q.front(); 64 q.pop();vis[u]=0; 65 for(int i=head1[u];i!=-1;i=e1[i].next) 66 { 67 int v=e1[i].v,w=e1[i].w; 68 if(dis1[v]>dis1[u]+w) 69 { 70 dis1[v]=dis1[u]+w; 71 if(vis[v]==0) 72 { 73 q.push(v); 74 vis[v]=1; 75 } 76 } 77 } 78 } 79 } 80 81 int main() 82 { 83 scanf("%d%d%d",&n,&m,&s); 84 memset(head,-1,sizeof(head)); 85 memset(head1,-1,sizeof(head1)); 86 memset(vis,0,sizeof(vis)); 87 memset(dis,0x3f3f3f3f,sizeof(dis)); 88 memset(dis1,0x3f3f3f3f,sizeof(dis1)); 89 for(int i=1;i<=m;i++) 90 { 91 int u,w,v; 92 scanf("%d%d%d",&u,&v,&w); 93 add(u,v,w); 94 add1(v,u,w); 95 } 96 spfa(); 97 memset(vis,0,sizeof(vis)); 98 spfa1(); 99 int ans=-1; 100 for(int i=1;i<=n;i++) 101 ans=max(dis[i]+dis1[i],ans); 102 printf("%d",ans); 103 return 0; 104 }