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

    题目描述

    Farmer John has decided to assemble a panoramic photo of a lineup of his N cows (1 <= N <= 200,000), which, as always, are conveniently numbered from 1..N. Accordingly, he snapped M (1 <= M <= 100,000) photos, each covering a contiguous range of cows: photo i contains cows a_i through b_i inclusive. The photos collectively may not necessarily cover every single cow.

    After taking his photos, FJ notices a very interesting phenomenon: each photo he took contains exactly one cow with spots! FJ was aware that he had some number of spotted cows in his herd, but he had never actually counted them. Based on his photos, please determine the maximum possible number of spotted cows that could exist in his herd. Output -1 if there is no possible assignment of spots to cows consistent with FJ's photographic results.

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

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

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

    Input

    输入输出格式

    输入格式:

    * Line 1: Two integers N and M.

    * Lines 2..M+1: Line i+1 contains a_i and b_i.

    输出格式:

    * Line 1: The maximum possible number of spotted cows on FJ's farm, or -1 if there is no possible solution.

    输入输出样例

    输入样例#1:
    5 3 
    1 4 
    2 5 
    3 4 
    
    输出样例#1:
    1 
    

    说明

    There are 5 cows and 3 photos. The first photo contains cows 1 through 4, etc.

    From the last photo, we know that either cow 3 or cow 4 must be spotted. By choosing either of these, we satisfy the first two photos as well.

    题解

    • 真的是卡spfa卡的不亦乐乎!
    • 题目大意:给定n个区间,每个区间中只有一头斑点牛,求最多可能有多少头斑点牛
    • 每个区间最少只有一头斑点牛,也最多只有一头斑点牛
    • 那么一只奶牛要不就是斑点牛,要不就是正常牛,那么就是0<=sum[i]-sum[i-1]<=1
    • 转移一下sum[R]-sum[L-1]<=1,sum[L-1]-sum[R]<=-1
    • 那么就可以差分约束,把i和i-1之间连一条0边,i-1和i之间连一条1边,a-1和b之间连一条1边,b和a-1之间连一条-1边
    • 如何跑一个优秀的spfa才是重点,可以用双向队列优化spfa

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <queue>
     4 #define N 200010
     5 #define inf 0x7fffffff
     6 using namespace std;
     7 struct edge {int to,from,v;}e[N*4];
     8 int n,m,vis[N*2],dis[N*2],head[N*2],cnt=1,tot;
     9 void insert(int x,int y,int v) { e[++cnt].to=y,e[cnt].from=head[x],e[cnt].v=v,head[x]=cnt; }
    10 int spfa()
    11 {
    12     deque<int> Q;
    13     for (int i=1;i<=n;i++) dis[i]=inf;
    14     vis[0]=1,Q.push_back(0);
    15     while (Q.size())
    16     {
    17         int u=Q.front(); Q.pop_front(),vis[u]=0;
    18         for (int i=head[u];i;i=e[i].from)
    19             if (dis[e[i].to]>dis[u]+e[i].v)
    20             {
    21                 dis[e[i].to]=dis[u]+e[i].v;
    22                 if (!vis[e[i].to])
    23                 {
    24                     if (++tot>1926817) return -1;
    25                     vis[e[i].to]=1;
    26                     if (Q.size()&&dis[e[i].to]>dis[Q.front()]) Q.push_back(e[i].to); else Q.push_front(e[i].to);
    27                 }
    28             }
    29     }
    30     return dis[n];
    31 }
    32 int main()
    33 {
    34     scanf("%d%d",&n,&m);
    35     for (int i=1,l,r;i<=m;i++) scanf("%d%d",&l,&r),insert(l-1,r,1),insert(r,l-1,-1);
    36     for (int i=1;i<=n;i++) insert(i-1,i,1),insert(i,i-1,0);
    37     printf("%d
    ",spfa());
    38 }
  • 相关阅读:
    C# Note23: 如何自定义类型使用foreach循环
    C# Note22: 《Effective C#》笔记
    C# Note21: 扩展方法(Extension Method)及其应用
    C# Note20: 制作延时改变显示的标题栏
    C# Note19: Windows安装包制作实践
    Python Note1: Pycharm的安装与使用
    java Html&JavaScript面试题:HTML 的 form 提交之前如何验证数值文本框的内容全部为数字? 否则的话提示用户并终止提交?
    java Html&JavaScript面试题:用table显示n条记录,每3行换一次颜色,即1,2,3用红色字体,4,5,6用绿色字体,7,8,9用红颜色字体。
    java Html&JavaScript面试题:判断第二个日期比第一个日期大
    java算法面试题:金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。
  • 原文地址:https://www.cnblogs.com/Comfortable/p/10301176.html
Copyright © 2011-2022 走看看