zoukankan      html  css  js  c++  java
  • spfa算法

    例题一:POJ-3259 Wormholes(判负环)

     

    While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

    As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

    To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

    Input

    Line 1: A single integer, FF farm descriptions follow. 
    Line 1 of each farm: Three space-separated integers respectively: NM, and W 
    Lines 2.. M+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
    Lines M+2.. MW+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: A one way path from S to E that also moves the traveler backT seconds.

    Output

    Lines 1.. F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

    Sample Input

    2
    3 3 1
    1 2 2
    1 3 4
    2 3 1
    3 1 3
    3 2 1
    1 2 3
    2 3 4
    3 1 8

    Sample Output

    NO
    YES

    Hint

    For farm 1, FJ cannot travel back in time. 
    For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

    描述

    在探索他的许多农场时,约翰农夫发现了许多惊人的虫洞。一个虫洞非常奇特,因为它是一条单向的路径,可以在您进入虫洞之前将它送到目的地!每个FJ的农场包括N(1≤N≤500)方便地编号1..N,M(1≤边号≤2500)路径字段和W(1≤w≤200)虫洞。

    由于FJ是一个狂热的时间旅行爱好者,他想要做到以下几点:从某个领域开始,穿过一些路径和虫洞,并在他最初离开之前的一段时间返回起跑场。也许他将能够见到自己:)。

    为了帮助FJ发现这是否可行,他会为你提供完整的地图给他的农场的F(1≤F≤5)。没有路径需要超过10,000秒的时间才能移动,并且没有虫洞可以使FJ在时间上超过10,000秒。 

    题目的大意是给你若干条 正权双向边 和 负权单项边 来建图,问你是否有负权回路。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn=100000;
    struct node{
        int to;
        int next;
        int w;
    }e[maxn];
    int flag;
    int dis[maxn];
    int head[maxn],cn[maxn],sum[maxn],vis[maxn];
    int cnt,m,n;
    void init()
    {
        memset(dis,inf,sizeof(dis));
        memset(head,-1,sizeof(head));
        memset(cn,0,sizeof(cn));
        memset(sum,0,sizeof(sum));
        memset(vis,0,sizeof(vis));
        cnt=0;
    }
    void add(int x,int y,int d)
    {
        e[cnt].to=y;
        e[cnt].w=d;
        e[cnt].next=head[x];
        head[x]=cnt++; 
    } 
    void spfa()
    {
        queue<int>q;
        q.push(1);
        dis[1]=0;
        vis[1]=1;
        while(!q.empty())
        {
            int u=q.front();
            vis[u]=0;
            q.pop();
            for(int i=head[u];i!=-1;i=e[i].next)
            {
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].w)
                {
                    dis[v]=dis[u]+e[i].w;
                    if(!vis[v])
                    {
                        sum[v]++;
                        vis[v]=1;
                        q.push(v);
                        if(sum[v]>=n)
                        {
                            flag=1;
                            break;
                        }
                    }
                }
            }
         if(flag)
             break;
        }
    }
    int main()
    {
        int casen,c;
        cin>>casen;
        while(casen--)
        {
            init();
            flag=0;
            scanf("%d%d%d",&n,&m,&c);
            int x,y,z;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
                add(y,x,z);
            }
            for(int i=0;i<c;i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,-z);
            }
            spfa();
            if(flag)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
    return 0;
    }

    例题二 POJ - 2240

    题意:

    已知n种货币,以及m种货币汇率及方式,问能否通过货币转换,使得财富增加。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #include<map>
      6 #include<vector>
      7 #include<algorithm>
      8 #define inf 0x3f3f3f3f
      9 using namespace std;
     10 typedef long long ll;
     11 string s1,s2;
     12 const int maxn=1100;
     13 int m,n;
     14 struct node{
     15     int to;
     16     int next;
     17     double d;
     18 }e[maxn];
     19 int vis[maxn],f[maxn],head[maxn],cn[maxn];
     20 double dis[maxn],w;
     21 int cnt,sx;
     22 int t=1;
     23 int  flag;
     24 map<string,int>mp;
     25 void init()
     26 {
     27     memset(head,-1,sizeof(head));
     28     memset(vis,0,sizeof(vis));
     29     memset(dis,0,sizeof(dis));
     30     memset(cn,0,sizeof(cn));
     31     memset(f,0,sizeof(f));
     32     cnt=0;
     33 }
     34 void add(int x,int y,double w)
     35 {
     36     e[cnt].to=y;
     37     e[cnt].d=w;
     38     e[cnt].next=head[x];
     39     head[x]=cnt++;
     40 }
     41 void spfa()
     42 {
     43     memset(vis,0,sizeof(vis));
     44     memset(dis,0,sizeof(dis));
     45     memset(cn,0,sizeof(cn));
     46     memset(f,0,sizeof(f));
     47      flag=0;
     48     dis[sx]=1.0;
     49     queue<int>q;
     50     while(!q.empty())q.pop();
     51     q.push(sx);
     52     vis[sx]=1;
     53     while(!q.empty())
     54     {
     55         int u=q.front();
     56         vis[u]=0;
     57         q.pop();
     58         if(cn[u]>=n&&vis[u]==0)//只要找到有能成正环的,就一定可以使每个点的值无限增大,一定可以达到指定值,所以为了节省时间,找到正环,即将该点值定义为inf,跳出循环。 
     59         {
     60             dis[u]=inf;
     61             vis[u]=1;
     62         }
     63         if(dis[sx]>1)
     64         {
     65             flag=1;
     66             return;
     67         }
     68         for(int i=head[u];i!=-1;i=e[i].next)
     69         {
     70             int v=e[i].to;
     71             if(dis[v]<dis[u]*e[i].d)
     72             {
     73                 dis[v]=dis[u]*e[i].d;
     74                 cn[v]++;
     75                 if(vis[v]==0)
     76                 {
     77                     vis[v]=1;
     78                     q.push(v); 
     79                 }
     80             }
     81         }
     82      if(flag)
     83          break;
     84     }
     85     
     86 }
     87 int main()
     88 {
     89     
     90     while(~scanf("%d",&n))
     91     {int id=1;
     92         init();
     93         flag=0;
     94         if(n==0)
     95             break;
     96         for(int i=1;i<=n;i++)
     97         {
     98             cin>>s1;
     99             mp[s1]=id++; 
    100         }
    101         scanf("%d",&m);
    102         for(int i=0;i<m;i++)
    103         {
    104             cin>>s1>>w>>s2;
    105             add(mp[s1],mp[s2],w);
    106         }
    107         for(int i=1;i<=n;i++)
    108         { 
    109             memset(vis,0,sizeof(vis));
    110             memset(dis,0,sizeof(dis));
    111             memset(cn,0,sizeof(cn));
    112             sx=i;
    113             spfa();
    114             if(flag)
    115             break;
    116         }
    117          if(flag)
    118          {
    119             printf("Case %d: Yes
    ",t++);
    120          }
    121          else
    122             printf("Case %d: No
    ",t++);
    123         
    124     }
    125 return 0;
    126 }

     

  • 相关阅读:
    python简单文件服务器
    Qt5WebSockets
    cartographer ros 配置项
    ubuntu18.04 evo 测评工具安装
    ubuntu18.04 orb_slam2安装记录
    clonezilla使用说明
    会计报名
    将博客搬至CSDN
    JS--微信浏览器复制到剪贴板实现
    Python--Django学习笔记2
  • 原文地址:https://www.cnblogs.com/1013star/p/9426213.html
Copyright © 2011-2022 走看看