• LightOJ 1074 spfa判断负环


    题意是给出一个有向图 给出一定的边 可以求出边权 求单源最短路 如果<3 或者 达不到 输出问号 不然输出dis[v]

    一开始耿直的写了一个dij交上去 还过了样例 然后wa掉 看了看题 发现其中有负权边 并且应该是可以达到负环的 比如3->1->2->3 所以<3是判断 这个点能否是负的 或者 它的确小于3

    如果一个点在负环中 那么dis[it]可以是无限小 那么它所能到达的所有点 都可以是无限小 

    使用spfa判断 当一个点被证实是在负环中 dfs它 把它与它能到达的所有的点标记

    需要注意的是 松弛的时候判断松弛边的起点有没有被标记 如果它被标记过 说明 它能松弛的那个点一定也被标记过了 那么就跳过这个边就可以了

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<math.h>
    #include<queue>
    using namespace std;
    int a[205];
    int n,m,q;
    struct node
    {
        int v;
        int w;
        int nex;
    };
    int l(int x)
    {
        return x*x*x;
    }
    node b[40050];
    int point[205];
    int cnt;
    void add(int u,int v,int w)
    {
        b[cnt].v=v;
        b[cnt].w=w;
        b[cnt].nex=point[u];
        point[u]=cnt;
        cnt++;
    }
    bool vis[205];
    int dis[205];
    int c[205];
    bool f[205];
    void dfs(int u)
    {
        f[u]=true;
        for(int tt=point[u];tt!=-1;tt=b[tt].nex)
        {
            int v=b[tt].v;
            if(f[v]==false)
            {
                dfs(v);
            }
        }
    }
    void spfa()
    {
        for(int i=1;i<=n;i++)
            dis[i]=999999999;
        dis[1]=0;
        for(int i=1;i<=n;i++)
            vis[i]=true;
        for(int i=1;i<=n;i++)
            c[i]=0;
        for(int i=1;i<=n;i++)
            f[i]=false;
        vis[1]=false;
        c[1]++;
        queue<int >q;
        q.push(1);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            vis[u]=true;
            for(int tt=point[u];tt!=-1;tt=b[tt].nex)
            {
                int v=b[tt].v;
                int w=b[tt].w;
                if(dis[v]>dis[u]+w&&f[u]==false) /// 如果不加上f[u]==false 会超时 如果f[u]==true 那么说明它能到达的点(松弛的点)一定也是f[v]==true 了
                {
                    dis[v]=dis[u]+w;
                    if(vis[v])
                    {
                        vis[v]=false;
                        c[v]++;
                        if(c[v]>=n&&f[v]==false)
                        {
                            dfs(v);
                        }
                        else
                        {
                            q.push(v);
                        }
                    }
                }
            }
        }
    }
    
    int main(){
    int t;
    int tt=0;
    scanf("%d",&t);
    while(t--)
    {
        tt++;
        cnt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            point[i]=-1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            int w;
            scanf("%d%d",&u,&v);
            w=l(a[v]-a[u]);
            add(u,v,w);
        }
        scanf("%d",&q);
        spfa();
        printf("Case %d:
    ",tt);
        for(int i=1;i<=q;i++)
        {
            int x;
            scanf("%d",&x);
            int ans=dis[x];
            if(ans<3||ans==999999999)
                printf("?
    ");
            else
               printf("%d
    ",ans);
        }
    }
    }
    

      

  • 相关阅读:
    紫微斗数诸星分级及分类
    n次独立重复试验暨伯努利试验
    信息系统项目管理师上午综合知识试题解析: 项目集治理
    三点估算和PERT技术
    自己写操作系统---bootsector篇
    硬盘分区表知识—详解硬盘MBR
    如何在自定义端口上运行 Spring Boot 应用程序?
    查询所有同学的学号、姓名、选课数、总成绩
    查询平均成绩大于60分的同学的学号和平均成绩
    查询“001”课程比“002”课程成绩高的所有学生的学号;
  • 原文地址:https://www.cnblogs.com/rayrayrainrain/p/5554148.html
Copyright © 2020-2023  润新知