L - The Shortest Path Gym - 101498L (dfs式spfa判断负环)
题目链接:https://cn.vjudge.net/contest/283066#problem/L
题目大意:T组测试样例,n个点,m条边,每一条边的信息是起点,终点,边权。问你是不是存在负环,如果存在的话输出-inf,否则的话,输出最小路径(两个点之间)。
具体思路:一般的spfa只能判断一个点到其他点的最短距离,但是这个题目让我们求的是任意两个点之间的,所以我们可以通过超级源点的建立,从超级源点到每一个点都引一条边权为0的边,然后通过超级源点作为spfa的起点,就可以判断出最短距离了。
ps:当所有的边权都大于0的时候,这种情况需要特殊讨论,因为spfa的0点的初始边权是0,如果按照spfa的话,根本不会进入循环,因为只要一进入循环,dis就会增大。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<cmath> 4 #include<cstring> 5 #include<stdio.h> 6 #include<map> 7 #include<queue> 8 #include<algorithm> 9 using namespace std; 10 # define ll long long 11 # define inf 0x3f3f3f3f 12 const int mod = 1e9+7; 13 const int maxn = 2e4+100; 14 const int maxedge= 5e4+100; 15 int vis[maxn],head[maxn]; 16 int dis[maxn]; 17 int num,flag; 18 struct node 19 { 20 int fr; 21 int to; 22 int cost; 23 int nex; 24 } edge[maxedge]; 25 void spfa(int u) 26 { 27 if(flag)return ; 28 vis[u]=1; 29 for(int i=head[u]; i!=-1; i=edge[i].nex) 30 { 31 int v=edge[i].to; 32 if(dis[u]+edge[i].cost<dis[v]) 33 { 34 dis[v]=dis[u]+edge[i].cost; 35 if(vis[v]) 36 { 37 flag=1; 38 } 39 else 40 spfa(v); 41 } 42 } 43 vis[u]=0; 44 } 45 void init() 46 { 47 memset(vis,0,sizeof(vis)); 48 memset(head,-1,sizeof(head)); 49 memset(dis,inf,sizeof(dis)); 50 num=0; 51 flag=0; 52 } 53 void addedge(int fr,int to,int cost) 54 { 55 edge[num].to=to; 56 edge[num].cost=cost; 57 edge[num].nex=head[fr]; 58 head[fr]=num++; 59 } 60 int main() 61 { 62 int T; 63 scanf("%d",&T); 64 while(T--) 65 { 66 init(); 67 int n,m; 68 scanf("%d %d",&n,&m); 69 int t1,t2,t3; 70 int minn=inf; 71 for(int i=1; i<=m; i++) 72 { 73 scanf("%d %d %d",&t1,&t2,&t3); 74 addedge(t1,t2,t3); 75 minn=min(minn,t3); 76 } 77 // if(minn>=0){ 78 // printf("%d\n",minn); 79 // continue; 80 // } 81 for(int i=1; i<=n; i++) 82 { 83 addedge(0,i,0); 84 } 85 dis[0]=0; 86 spfa(0); 87 if(flag) 88 printf("-inf\n"); 89 else 90 { 91 int minn=inf; 92 for(int i=1; i<=n; i++) 93 { 94 minn=min(minn,dis[i]); 95 } 96 printf("%d\n",minn); 97 } 98 } 99 return 0; 100 }