zoukankan      html  css  js  c++  java
  • P3084 [USACO13OPEN]照片Photo 差分约束

      

    农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N。

    于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛。但是这些照片不一定把每一只奶牛都拍了进去。

    在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有且仅有一只身上带有斑点的奶牛。约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量。 根据照片,请你帮约翰估算在他的牛群中最多可能有多少只斑点奶牛。如果无解,输出“-1”。

    很容易想到差分约束  而且边也很好建   唯一要考虑的是spfa  果然又被卡了

    采用双端队列优化   且遍历了一定的值以后直接退出即可

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3
    const int N=200000+5;
    const int M=10*N;
    int n,k;
    int pos,head[M],tot;
    struct Edge
    {
        int nex,to,v;
    }edge[M];
    void add(int a,int b,int c)
    {
        edge[++pos].nex=head[a];
        head[a]=pos;
        edge[pos].to=b;
        edge[pos].v=c;
    }
    int dis[N];
    int vis[N];
    int cnt[N];
    
    int spfa()
    {
        deque<int>q;
        rep(i,1,n)dis[i]=inf;
        dis[0]=0;
        vis[0]=1;
        q.push_back(0);
        while(!q.empty())
        {
            int x=q.front();
            q.pop_front();
            vis[x]=0;
            for(int i=head[x];i;i=edge[i].nex)
            {
                int v=edge[i].to,w=edge[i].v;
                if(dis[v]>dis[x]+w)
                {
                    dis[v]=dis[x]+w;
                    if(!vis[v])
                    {
                        if(++tot>800000)return 0;
                        vis[v]=1;
                        if(q.size()&&dis[v]>dis[q.front()])q.push_back(v);
                        else q.push_front(v);
                    }
                }
            }
        }
        return dis[n];
    }
    
    int main()
    {
        cin>>n>>k;
    
        rep(i,1,k)
        {
            int a,b;cin>>a>>b;
            add(a-1,b,1);add(b,a-1,-1);
        }
        rep(i,1,n)add(i-1,i,1),add(i,i-1,0);
    
        if(spfa())
            cout<<dis[n];
        else cout<<"-1";
    
        return 0;
    }
    View Code

    一般这种求最多的 要用最短路   (也就是  <=  式子 )

    求最少的  用最长路

  • 相关阅读:
    java异常
    Map集和
    获取每个字符出现的次数
    从1-33号球中选取6个红球,且红球数字最多重复不超过3个 从1-16号球中选取一个篮球 由红球和蓝球共同组成一个双色球号码,且红球在左边(按照升序排列),篮球在右边。
    gitlab介绍及使用
    Maven使用介绍
    IDEA集成开发环境安装git,修改代码后文件变色代表的含义
    大数据相关
    开源镜像站汇总
    MySQL配置文件详解
  • 原文地址:https://www.cnblogs.com/bxd123/p/11394796.html
Copyright © 2011-2022 走看看