• 差分约束总结


      遇到了一些很不错的差分约束系统的题目 我觉得需要总结一下的样子。

    LINK:种树 万壑树参天 千山响杜鹃  差分约束 觉得海星 由于每个位置只能种一棵树和区间的限定我们不难想到 利用前缀和数组来建图。

    显然 有条件 dr-dr-1<=1 dr-dr-1>=0 和某些去加问题 dr-dl-1>=cnt 什么 的通过建图 我们发现要构造出来的解其实就是 d数组了。

    考虑 一下怎么跑?从哪开始跑 好像没有一个起点的样子 虚设源点 从而进行构解 源点如果为 0的话 好像没有什么约束条件的样子但是源点设为 n+1 那么则有 dn+1-di>=0

    这个条件 我们设dn+1=0 构造出来一组负数解 即可 考虑如何满足最小的取值 我觉的是 由于跑的是最短路 所以求出的解必然是一组 可能不符合实际意义但是是最优的解 。

    所以我们调整一下即可 全部都减去最小的 最小的显然是dis[1] 由于dis n+1为0 答案就为 disn+1-dis[1] ==-dis[1]了。(我觉得应该没锅

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<cstdlib>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #include<stack>
    #include<iomanip>
    #define INF 1000000010
    #define ll long long
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define db double
    #define EPS 1e-5
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define sum(p) t[p].sum
    #define zz p<<1
    #define yy p<<1|1
    #define mod 1000000007
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=30010;
    int n,flag,ans;
    int m,len,t,h,minn=INF;
    int dis[MAXN],vis[MAXN],v[MAXN],q[MAXN<<5];
    int lin[MAXN],nex[MAXN<<2],ver[MAXN<<2],e[MAXN<<2];
    inline void add(int x,int y,int z)
    {
        ver[++len]=y;
        nex[len]=lin[x];
        lin[x]=len;
        e[len]=z;
    }
    inline void spfa()
    {
        while(h++<t)
        {
            int x=q[h];vis[x]=0;
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(dis[tn]>dis[x]+e[i])
                {
                    v[tn]=v[x]+1;
                    if(v[tn]>=n){flag=1;return;}
                    dis[tn]=dis[x]+e[i];
                    if(!vis[tn])q[++t]=tn,vis[tn]=1;
                }
            }
        }
    }
    signed main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();++n;
        memset(dis,0x3f,sizeof(dis));
        for(int i=1;i<n;++i)
        {
            add(i,i+1,1),add(i+1,i,0);
            add(n,i,0);
        }
        for(int i=1;i<=m;++i)
        {
            int x,y,z;
            x=read();y=read()+1;z=read();
            add(y,x,-z);
        }
        q[++t]=n;dis[n]=0;
        spfa();
        printf("%d
    ",-dis[1]);
        return 0;
    }
    View Code

    LINK:狡猾的商人 商人 总是 具有高雅的智慧吧。

    还是考虑前缀和建图 不过不同的是 某个区间特定的值是有了我们是这样转换的 dr-dl-1>=w dr-dl-1<=w

    所以就可以直接跑了 ...

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<queue>
    #include<iomanip>
    #include<cctype>
    #include<cstdio>
    #include<deque>
    #include<utility>
    #include<cmath>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    #include<stack>
    #include<map>
    #include<set>
    #include<bitset>
    #define INF 1000000000
    #define ll long long
    #define db double
    #define mod 1000000007
    #define pii pair<ll,ll>
    #define mk make_pair
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define sum(p) t[p].sum
    #define zz p<<1
    #define yy p<<1|1
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=110,maxn=1010;
    int T,len,t,h;
    int n,m,flag;
    int lin[MAXN],nex[maxn<<1],ver[maxn<<1],e[maxn<<1];
    int vis[MAXN],dis[MAXN],v[MAXN],q[MAXN*MAXN];
    inline void add(int x,int y,int z)
    {
        ver[++len]=y;
        nex[len]=lin[x];
        lin[x]=len;
        e[len]=z;
    }
    inline void spfa()
    {
        while(h++<t)
        {
            int x=q[h];vis[x]=0;
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(dis[x]+e[i]<dis[tn])
                {
                    dis[tn]=dis[x]+e[i];
                    v[tn]=v[x]+1;
                    if(v[tn]>=n){flag=1;return;}
                    if(!vis[tn])q[++t]=tn,vis[tn]=1;
                }
            }
        }
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        T=read();
        while(T--)
        {
            flag=0;len=0;
            memset(lin,0,sizeof(lin));
            n=read();m=read();++n;
            for(int i=1;i<=m;++i)
            {
                int l,r,z;
                l=read();r=read()+1;z=read();
                add(l,r,z);
                add(r,l,-z);
            }
            t=h=0;
            for(int i=1;i<=n;++i)
            {
                q[++t]=i;
                v[i]=dis[i]=vis[i]=0;
            }
            spfa();
            if(flag)puts("false");
            else puts("true");
        }
        return 0;
    }
    View Code

    LINK:天平 其实在我的眼中天平从来都没有平过..毫无用处的东西...

    这题就很神了 很鬼畜的样子 发现差分约束总是 要对建图有一定的要求。

    有一堆约束条件 但是可能有未知的砝码 所以最后我们利用spfa构造的只是其中的一种很难完成题目中所说的 确定的情况。

    神仙题目 原来跑的是floyd 处理差分约束的关系。可以设两个数字 d[i][j] 表示i和j砝码最多差多少克 b i j 表示i和j砝码最少差多少克。

    这个东西可以利用floyd实现 这个东西 然后最后求的话其实就是暴力枚举两个东西 判断即可。

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<cstdlib>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #include<stack>
    #include<iomanip>
    #define INF 100000000000000000ll
    #define ll long long
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define db double
    #define EPS 1e-5
    #define mod 1000000007
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=60;
    int n;
    int A,B,ans1,ans2,ans3;
    int d[MAXN][MAXN],b[MAXN][MAXN];
    char a[MAXN][MAXN];
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();A=read();B=read();
        for(int i=1;i<=n;++i)
        {
            scanf("%s",a[i]+1);
            for(int j=1;j<=n;++j)
            {
                if(a[i][j]=='?')d[i][j]=2,b[i][j]=-2;
                if(a[i][j]=='+')d[i][j]=2,b[i][j]=1;
                if(a[i][j]=='-')d[i][j]=-1,b[i][j]=-2;
                if(a[i][j]=='=')d[i][j]=b[i][j]=0;
            }
        }
        for(int k=1;k<=n;++k)
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                {
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
                    b[i][j]=max(b[i][j],b[i][k]+b[k][j]);
                }
        for(int i=1;i<=n;++i)
        {
            if(i==A||i==B)continue;
            for(int j=i+1;j<=n;++j)
            {
                if(j==A||j==B)continue;
                if(b[A][i]>d[j][B]||b[B][i]>d[j][A])++ans1;
                if(b[i][A]>d[B][j]||b[j][A]>d[B][i])++ans3;
                if((b[A][i]==d[A][i]&&b[j][B]==d[j][B]&&b[A][i]==b[j][B])||(b[A][j]==d[A][j]&&b[i][B]==d[i][B]&&b[A][j]==b[i][B]))++ans2;
            }
        }
        printf("%d %d %d
    ",ans1,ans2,ans3);
        return 0;
    }
    View Code
  • 相关阅读:
    12_springmvc拦截器
    11_springmvc之RESTful支持
    10_springmvc JSON数据交互
    09_springmvc图片上传
    09_springmvc异常处理
    08_springmvc数据回显和@ModelAttribute注解详解
    Eclipse-----解决调试源码不进入断点问题
    JavaScript-----截取字符串的常用方法
    排序(Sort)-----冒泡排序
    SpringMVC探究-----常用获取传递参数的方法
  • 原文地址:https://www.cnblogs.com/chdy/p/11676172.html
Copyright © 2020-2023  润新知