• Easy sssp


    Easy sssp

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 103  解决: 20
    [提交][状态][讨论版]

    题目描述

    输入数据给出一个有N(2  < =  N  < =  1,000)个节点,M(M  < =  100,000)条边的带权有向图.  要求你写一个程序,  判断这个有向图中是否存在负权回路.  如果从一个点沿着某条路径出发,  又回到了自己,  而且所经过的边上的权和小于0,  就说这条路是一个负权回路. 如果存在负权回路,  只输出一行-1; 如果不存在负权回路,  再求出一个点S(1  < =  S  < =  N)到每个点的最短路的长度.  约定:    S到S的距离为0,  如果S与这个点不连通,  则输出NoPath.

    输入

    第一行:  点数N(2  < =  N  < =  1,000),  边数M(M  < =  100,000),  源点S(1  < =  S  < =  N); 以下M行,  每行三个整数a,  b,  c表示点a,  b(1  < =  a,  b  < =  N)之间连有一条边,  权值为c(-1,000,000  < =  c  < =  1,000,000)

    输出

    如果存在负权环,  只输出一行-1,  否则按以下格式输出 共N行,  第i行描述S点到点i的最短路:  如果S与i不连通,  输出NoPath; 如果i  =  S,  输出0; 其他情况输出S到i的最短路的长度.

    样例输入

    6 8 1
    1 3 4
    1 2 6
    3 4 -7
    6 4 2
    2 4 5
    3 6 3
    4 5 1
    3 5 4
    

    样例输出

    0
    6
    4
    -3
    -2
    7
    

    提示

    做这道题时,  你不必为超时担心,  不必为不会算法担心,  但是如此“简单”的题目,  你究竟能ac么?

     题解:这是一道spfa的题目吧,考点是spfa的应用和spfa判断负权回路的问题,每个块都判断一次,若其中有一个块存在负权回路,则直接输出NoPath;如果不存在,则输出最短路即可。

        spfa判断负环应该都知道吧,一个点如果进栈n次存在负环

      1 #include<cstdio> 
      2 #include<algorithm> 
      3 #include<cmath> 
      4 #include<iostream> 
      5 #include<string> 
      6 #include<cstring> 
      7   
      8 using namespace std; 
      9 const int MAXN=1007,MAXM=100007; 
     10   
     11 int num,first[MAXN],next[MAXM],arr[MAXM],cost[MAXM]; 
     12 int times[MAXN]; 
     13 int n,m,st; 
     14 int p[MAXN]; 
     15 bool boo[MAXN],he[MAXN]; 
     16 long long dis[MAXN]; 
     17   
     18 void add(int u,int v,int z) 
     19 { 
     20     num++; 
     21     next[num]=first[u]; 
     22     first[u]=num; 
     23     arr[num]=v; 
     24     cost[num]=z; 
     25 } 
     26 void init() 
     27 { 
     28     memset(he,0,sizeof(he)); 
     29     memset(times,0,sizeof(times)); 
     30     memset(boo,0,sizeof(boo)); 
     31     memset(next,0,sizeof(next)); 
     32     memset(arr,0,sizeof(arr)); 
     33     memset(cost,0,sizeof(cost)); 
     34     for (int i=1;i<=n;i++) 
     35         first[i]=-1; 
     36     num=0;   
     37     for (int i=1;i<=n;i++) 
     38         dis[i]=100000007; 
     39     dis[st]=0;   
     40 } 
     41 bool pan(int st) 
     42 { 
     43     int head=0,tail=1; 
     44     p[tail]=st,boo[st]=1; 
     45     times[st]++; 
     46       
     47     while (head!=tail) 
     48     { 
     49         head=head%n+1; 
     50         int u=p[head],v; 
     51         for (int i=first[u];i!=-1;i=next[i]) 
     52         { 
     53             v=arr[i]; 
     54             if (dis[u]+cost[i]<dis[v]) 
     55             { 
     56                 dis[v]=dis[u]+cost[i]; 
     57                 if (boo[v]==0) 
     58                 { 
     59                     times[v]++; 
     60                     if (times[v]>=n) 
     61                     { 
     62                         return 1; 
     63                     } 
     64                     boo[v]=1; 
     65                     tail=tail%n+1; 
     66                     p[tail]=v; 
     67                 } 
     68             } 
     69         } 
     70         boo[u]=0; 
     71     } 
     72     for (int i=1;i<=n;i++) 
     73         if (dis[i]<100000007) he[i]=1; 
     74     return 0; 
     75 } 
     76 void solve(int st) 
     77 { 
     78     int head=0,tail=1; 
     79     p[tail]=st,boo[st]=1; 
     80       
     81     while (head!=tail) 
     82     { 
     83         head=head%n+1; 
     84         int u=p[head],v; 
     85         for (int i=first[u];i!=-1;i=next[i]) 
     86         { 
     87             v=arr[i]; 
     88             if (dis[u]+cost[i]<dis[v]) 
     89             { 
     90                 dis[v]=dis[u]+cost[i]; 
     91                 if (boo[v]==0) 
     92                 { 
     93                     boo[v]=1; 
     94                     tail=tail%n+1; 
     95                     p[tail]=v; 
     96                 } 
     97             } 
     98         } 
     99         boo[u]=0; 
    100     } 
    101     for (int i=1;i<=n;i++) 
    102         if (dis[i]==100000007) printf("NoPath
    "); 
    103         else printf("%lld
    ",dis[i]); 
    104 } 
    105 int main() 
    106 { 
    107     scanf("%d%d%d",&n,&m,&st); 
    108     init();  
    109       
    110     int x,y,z; 
    111     for (int i=1;i<=m;i++) 
    112     { 
    113         scanf("%d%d%d",&x,&y,&z); 
    114         add(x,y,z); 
    115     } 
    116     for (int i=1;i<=n;i++) 
    117         if (he[i]==0)  
    118         { 
    119             for (int i=1;i<=n;i++) 
    120                 dis[i]=100000007; 
    121             dis[i]=0;    
    122             if (pan(i)) 
    123             { 
    124                 printf("-1
    "); 
    125                 return 0; 
    126             } 
    127             memset(boo,0,sizeof(boo)); 
    128             memset(times,0,sizeof(times)); 
    129         } 
    130     for (int i=1;i<=n;i++) 
    131         dis[i]=100000007; 
    132     dis[st]=0;   
    133     solve(st); 
    134 } 
    View Code
  • 相关阅读:
    dfs手写栈模板
    Remember the Word
    Sockets
    Sanatorium
    Exams
    Cormen — The Best Friend Of a Man
    win 7 普通家庭版 装IIS
    [引]构造文法时表达式中算符优先级的问题
    Chart系列(二):数据绑定
    算法整理篇之:数据结构 | 数组(1)
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/6977785.html
Copyright © 2020-2023  润新知