zoukankan      html  css  js  c++  java
  • 洛谷3385判负环模板

    题目:https://www.luogu.org/problemnew/show/P3385

    有DFS判负环的方法。参见《SPFA算法的优化及应用》(姜碧野)。

    摘录文中一段:

      首先假设初始时存在一个点s,从该点出发我们能找到正环(即以s为起点在环上走一圈,经过任意点时的dis[x]都大于0)。下面证明对环上某个点x的重赋值不会对正环的查找产生影响。
      假设x在环上的前驱为y。本来在寻找正环时dis[y]+w(y,x)>dis[x],然后继续从x开始迭代。而如果dis[x]被重赋值了dis[x]’>=dis[y]+w(y,x),看似迭代到x时就停止了,而如果dis[x]被重赋值了dis[x]’>=dis[y]+w(y,x),看似迭代到x时就停止了,而如果dis[x]被重赋值了dis[x]’>=dis[y]+w(y,x),看似迭代到x时就停止了,也不需要再从y过渡到x。两者并无区别。依次类推,必然可以找到一个导致正环的起点。
      而开始的假设则显然成立,否则我们可以把该正环分成若干段,每段的边权和<=0,与正环的前提矛盾,由此命题得证。

    其实略有点不懂。以后研究研究。

    对于本题,dfs只得40分,于是用快读+spfa手写队列做到1000+ms也就能AC了。

    用了一下循环队列,并觉得h!=t+1的条件挺好用的。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    const int N=4005,M=6005,INF=N<<5-5;
    int T,n,m,head[N],xnt,cnt[N],q[N<<5],h,t;
    ll dis[N];
    bool in[N];
    struct Edge{
        int next,to,w;
        Edge(int n=0,int t=0,int w=0):next(n),to(t),w(w) {}
    }edge[M<<1];
    int read()
    {
        int ret=0;char ch;bool fx=0;
        ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')fx=1;ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            ret=ret*10+(int)ch-'0';
            ch=getchar();
        }
        return fx?-ret:ret;
    }
    void add(int x,int y,int z)
    {
        edge[++xnt]=Edge(head[x],y,z);head[x]=xnt;
    }
    bool spfa()
    {
        memset(dis,1,sizeof dis);memset(in,0,sizeof in);
        memset(cnt,0,sizeof cnt);h=1;t=1;
        q[1]=1;in[1]=1;dis[1]=0;
        while(h!=t+1)
        {
            int k=q[h++];in[k]=0;if(h>INF)h=1;
            for(int i=head[k],v;i;i=edge[i].next)
                if(dis[k]+edge[i].w<dis[v=edge[i].to])
                {
                    dis[v]=dis[k]+edge[i].w;cnt[v]=cnt[k]+1;
                    if(cnt[v]>=n)return true;
                    if(!in[v])
                    {
                        in[v]=1;t++;
                        if(t>INF)t=1;q[t]=v;
                    }
                }
        }
        return false;
    }
    int main()
    {
        T=read();
        while(T--)
        {
            memset(head,0,sizeof head);xnt=0;
            n=read();m=read();int x,y,z;
            for(int i=1;i<=m;i++)
            {
                x=read();y=read();z=read();add(x,y,z);
                if(z>=0)add(y,x,z);
            }
            if(spfa())printf("YE5
    ");
            else printf("N0
    ");
        }
        return 0;
    }
  • 相关阅读:
    tomcat启动时报:IOException while loading persisted sessions: java.io.EOFException的解决方案
    Myeclispe 安装 SVN :
    Oracle数据库中SYS、SYSTEM、DBSNMP、SYSMAN四用户的区别
    转: Maven 仓库中添加Oracle JDBC驱动(11g)
    Ubuntu14.04的常用快捷键
    Ubuntu下常用的命令
    Ubuntu14.04 java环境配置
    主谓宾定状补
    Git的常用命令
    转:Android面试
  • 原文地址:https://www.cnblogs.com/Narh/p/8955893.html
Copyright © 2011-2022 走看看