zoukankan      html  css  js  c++  java
  • UVA 515 差分约束 SPFA判负

    第一次看这个题目,完全不知道怎么做,看起来又像是可以建个图进行搜索,但题目条件就给了你几个不等式,这是怎么个做法。。。之后google了下才知道还有个差分约束这样的东西,能够把不等式化成图,要求某个点在满足所有不等式的情况下的最大取值,只需对建好的图进行一次最短路即可

    不过要使得a b 点满足这样 a<=b+k这种不等式,还得对题目所给的不等式进行下改装

    原不等式无非就是 输入个 si ni,使得存在 A(si)+...A(si+ni)<k 或者 >k,我们新定义一个s[],s[i]代表从1 到 i的所有的点的和,这样,原不等式就会变成 s[si+ni]-s[si-1]>=k+1  或者 小于=k-1,进行下移项,即可变成差分约束不等式的形式,这样每个点的含义就是 对应的s[i]。

    此外注意添加一个超级原点 N+1,跟所有点进行下连通,保证图的连通性。

    其实题目还有个难点就是,他求是否能满足着m个不等式,如果不满足,意味着有相互冲突的不等式,也就是某个点值既可能正也可能负,也就是说图上存在负环。。。。这个转换确实比较难推敲,尤其是像我这种对图论题目还只是入门的菜鸟。

    因此,建好图后,只需用SPFA遍历一下,判断有无负环即可。

    此外,还有个疑惑,就是差分约束一定要有等于吗?就像上面的式子,如果不是为了满足=的条件,就不必用k+1和k-1来代替原来的k了。。。这个还有待考证

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define N 250
    using namespace std;
    int u[N],v[N],w[N],nt[N],ft[N/2],d[N/2],num[N/2],vis[N/2];
    int n,m,cnt,flag;
    void addedge(int a,int b,int c)
    {
        u[cnt]=a;
        v[cnt]=b;
        w[cnt]=c;
        nt[cnt]=ft[a];
        ft[a]=cnt++;
    }
    void spfa()
    {
        int i,j;
        for (i=0;i<=n;i++)
            d[i]=1<<30;
        memset(num,0,sizeof num);
        memset(vis,0,sizeof vis);
        flag=1;
        d[n+1]=0;
        queue <int> q;
        q.push(n+1);
        vis[n+1]=1;
        while (!q.empty())
        {
            int x=q.front();
            q.pop();
            vis[x]=0;
            num[x]++;
            if (num[x]>n)
            {
                flag=0;
                return;
            }
            for (i=ft[x];i>=0;i=nt[i])
            {
                int nx=v[i];
                if (d[nx]>d[x]+w[i])
                {
                    d[nx]=d[x]+w[i];
                    if (!vis[nx])
                    {
                        q.push(nx);
                        vis[nx]=1;
                    }
                }
            }
        }
    
    }
    int main()
    {
        int i,j;
        char ch[3];
        while (scanf("%d",&n))
        {
            if (!n) break;
            cnt=0;
            scanf("%d",&m);
            int a,b,k,si,ni;
            memset(ft,-1,sizeof ft);
            for (i=1;i<=m;i++)
            {
                scanf("%d%d%s%d",&si,&ni,ch,&k);
                if (ch[0]=='g')
                {
                    addedge(si+ni,si-1,(-k-1));//用差分约束不等式建图,下同
                }
                else
                {
                    addedge(si-1,si+ni,k-1);
                }
            }
            for (i=1;i<=n;i++) //将n+1作为超级原点进行连通。
                addedge(n+1,i,0);
            spfa();
            if (flag)
            {
                puts("lamentable kingdom");
    
            }
            else puts("successful conspiracy");
        }
        return 0;
    }
  • 相关阅读:
    跨浏览器的事件处理程序
    开发技术文档汇总
    JVM知识树
    JDK1.8新特性(一)
    CAS
    Redis集群之修改节点IP
    阿里云服务器 发送邮箱 STMP 25端口 465端口问题 Javamail 25被禁用
    日志log4j到Logback的使用(主要是Logback)
    ThreadLocal原理和 java类全局静态变量在多线程中数据混乱问题
    SpringMVC拦截器拦截页面(坑)
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3518860.html
Copyright © 2011-2022 走看看