POJ 1201/hdu 1384 Intervals【差分约束+SPFA】

Intervals

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3802    Accepted Submission(s): 1433

Problem 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 endpoints 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 <= 50 000) - 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 <= 50 000 and 1 <= ci <= bi - ai + 1.

Process to the end of file.

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

Author

1384

 

 题目大意:给出n个约束条件,表示在区间【a,b】上至少拿出c个元素,询问满足所有约束条件所构成的集合c中元素个数最少为多少个。

 

思路:差分约束转最短路。


差分约束转最短路问题首要思想就是要构成这样的一个式子就能构成一条有向边:

tb-ta<=k

那么我们的目标就是在已知条件中,转化问题为这个形式,我们也就能够转化问题到最短路上。

1、首先,我们需要对ti进行赋予含义:ti表示【0,i-1】中选取元素的个数,那么:tb+1-ta>=k,也就有:

ta-tb+1<=-k;

2、只有这个条件的话,图是不连通的,我们还有这样一个等式就能够使得图连通:

0<=ti-ti-1<=1

3、确定起点终点,起点就是所给约束条件中最小编号的节点,终点就是所给约束条件中最大编号的节点,然后我们进行一次SPFA,然后输出dis【终点】即可,对于负值的输出情况,我们转为正值即可。


AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int head[500000];
int vis[500000];
int dis[500000];
int n;
struct EdgeNode
{
    int to;
    int w;
    int next;
}e[500000];
int cont;
void add(int from,int to,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
int abs(int w)
{
    if(w<0)return -w;
    else return w;
}
void SPFA(int start)
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<=n;i++)dis[i]=INF;
    queue<int >s;
    s.push(start);
    vis[start]=1;
    dis[start]=0;
    while(!s.empty())
    {
        int u=s.front();
        s.pop();vis[u]=0;
        for(int j=head[u];j!=-1;j=e[j].next)
        {
            int v=e[j].to;
            int w=e[j].w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(vis[v]==0)
                {
                    s.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    printf("%d\n",abs(dis[n]));
}
int main()
{
    int m;
    int s;
    while(~scanf("%d",&m))
    {
        cont=0;
        n=0;
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        for(int i=0;i<m;i++)
        {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            s=min(s,x);
            n=max(n,y+1);
            add(x,y+1,-w);
        }
        for(int i=0;i<n;i++)
        {
            add(i+1,i,1);
            add(i,i+1,0);
        }
        SPFA(s);
    }
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值