POJ 1201 Intervals [差分约束系统]

该博客介绍了如何解决POJ 1201问题,即找到与给定n个区间至少有ci共同元素的最小整数集合Z的最小规模。通过解析输入的区间、目标数量ci,利用差分约束系统和图论中的SPFA算法求解。博主强调了题目中隐含的条件,并提供了问题的解决方案,包括构建模型并求解最短路径或最长路径。
摘要由CSDN通过智能技术生成

Intervals
Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu

Description
You are given n closed, integer intervals [ai, bi] and n integers c1, …, cn.
Write a program that:
reads the number of intervals, their end points and integers c1, …, cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,…,n,
writes the answer to the standard output.

Input
The first line of the input contains an integer n (1 <= n <= 50000) – the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.

Output
The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,…,n.

Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

Sample Output
6

Source
Southwestern Europe 2002


一开始每条边限制为 c ,但是还有隐含条件!!!
每个点有取或不取两种情况,那么 0<= s[i] - s[i-1] <=1 , 分别两边再求最短路或最长路即可。。(按照建模方式来。。。)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=50005;
struct Edge
{
    int to,next;
    int val;
}edge[maxn<<2];
int head[maxn];
int maxedge;
inline void addedge(int u,int v,int c)
{
    edge[++maxedge]=(Edge){v,head[u],c};
    head[u]=maxedge;
}
int n,minnode=INF,maxnode=-INF;
inline void init()
{
    scanf("%d",&n);
    memset(head,-1,sizeof(head));
    maxedge=-1;
    for(int i=1;i<=n;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        addedge(b+1,a,-c);//dis[i] representing Node i-1
        minnode=min(minnode,a);
        maxnode=max(maxnode,b+1);
    }
    for(int i=minnode;i<maxnode;i++)
    {
        addedge(i,i+1,1);
        addedge(i+1,i,0);
    }
}
int dis[maxn];
bool inque[maxn];
inline int spfa(int S,int T)
{
    deque <int> que;
    memset(dis,0x3f,sizeof(dis));
    dis[S]=0;inque[S]=true;
    que.push_back(S);
    int sum=0,tot=1;
    while(!que.empty())
    {
        int u=que.front();que.pop_front();
        if(dis[u]*tot>sum) { que.push_back(u);continue; }
        else inque[u]=false,tot--,sum-=dis[u];
        for(int i=head[u];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].val)
            {
                dis[v]=dis[u]+edge[i].val;
                if(inque[v]) continue;
                inque[v]=true;tot++,sum+=dis[v];
                if(!que.empty())
                    if(dis[v]<dis[que.front()]) que.push_front(v);
                    else que.push_back(v);
                else que.push_back(v);
            }
        }
    }
    return dis[T];
}
int main()
{
    #ifdef Local
    freopen("interval.in","r",stdin);
    freopen("interval.out","w",stdout);
    #endif
    init();
    cout<<-spfa(maxnode,minnode)<<endl;//shortest path needs to be reversed!
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值