zoukankan      html  css  js  c++  java
  • poj3169(我的第一个查分约束!)

    题目大意:有N头奶牛,编号从1到N,从左到右站成一排。有些奶牛互相喜欢,有些奶牛互相不喜欢。互相喜欢的奶牛有要求:互相喜欢的奶牛之间的距离不能超过一个值;同样,互相讨厌的奶牛之间的距离不能小于一个值。现在求在这样的要求下,1~N之间的距离的最大值。如果无法满足所有要求就输出-1,如果有无限种情况就输出-2,否则输出最大值。

    输入:                                           输出:          

    4 2 1                          27
    1 3 10
    2 4 20
    2 3 3

    解释:有四头牛,有两对互相喜欢,一对互相讨厌。两队喜欢的分别是1和3,要求距离不能大于10。另外一对是2,4,要求为20。讨厌的的一对是2,3,距离得不小于3。所以最大值为27。
    (1和2的距离为7,2和3的距离为3,3和4的距离为17)

    --->差分约束
    那么现在来分析这道题。
    假设互相喜欢的两头牛是a和b,那么dis[b]-dis[a]<=D(D为要求的值,dis[a]表示a到1的距离)
    互相讨厌的是c和d,那么dis[d]-dis[c]>=D ----> dis[c]-dis[d]<=-D
    因为距离是递增的,所以还有一个条件,s[i]-s[i-1]>=0 ----> s[i-1]-s[i]<=0
    不等式已经列出来了,现在可以建图了。(详见代码)
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int MAXN=1000+10;
    const int INF=0x3f3f3f3f;
    
    int n,ML,MD,cnt;
    int dis[MAXN],head[MAXN*MAXN],num[MAXN];
    bool vis[MAXN]; 
    struct node{
        int v,w,next;
    }e[MAXN*MAXN];
    
    int SPFA()
    {
        queue<int>q;
        memset(dis,INF,sizeof(dis));
        memset(num,0,sizeof(num));
        memset(vis,0,sizeof(vis));
        q.push(1);
        dis[1]=0;
        num[1]=1;
        vis[1]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].v,w=e[i].w;
                if(dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    if(!vis[v]){
                        if(++num[v]>n)
                            return -1;
                    }
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
        if(dis[n]==INF)    return -2;
        else return dis[n];
    }
    
    void Add(int a,int b,int c)
    {
        e[cnt].v=b;
        e[cnt].w=c;
        e[cnt].next=head[a];
        head[a]=cnt++;
    }
    
    int main(void)
    {
        
        while(~scanf("%d%d%d",&n,&ML,&MD)){
            memset(head,-1,sizeof(head));
            for(int i=1;i<=n;i++)
                Add(i,i-1,0);            //升序 所以  s[i]-s[i-1]>=0  ->  s[i-1]-s[i]<=0
                                        //我们可以把s[i]近似的看做i 
            for(int i=1,a,b,c;i<=ML;i++){
                scanf("%d%d%d",&a,&b,&c);
                if(a>b)    swap(a,b);
                Add(a,b,c);    
            }
                            //a like b,so b-a<=c  ->   b<=a+c
            for(int i=1,a,b,c;i<=MD;i++){
                scanf("%d%d%d",&a,&b,&c);
                if(a>b)    swap(a,b);
                Add(b,a,-c);
            }
                            //the same   b-a>=c   ->   a-b<=-c
            int ans=SPFA();
            printf("%d
    ",ans);
        }
            return 0;
    }//SnowCabbage
     
  • 相关阅读:
    米洛个人修炼术:导致上班累成狗的三大主因
    米洛个人修炼术:如何倍增你的功力修行速度达成健康体魄
    米洛个人修炼术:注意这三方面,天天都早起
    米洛个人修炼术:情绪的四种常用处理方式,其实都是有问题的
    好公司和差公司的对比
    课程作业二
    课程作业一
    作业四
    寒假作业三
    寒假作业二
  • 原文地址:https://www.cnblogs.com/LWJ2333/p/9679688.html
Copyright © 2011-2022 走看看