poj 1201 Interval

来源:互联网 发布:windows官网下载win10 编辑:程序博客网 时间:2024/06/08 01:15

题目链接:http://poj.org/problem?id=1201

题意:给你n个区间和每个区间至少要出多少个数,问你整个区间最少需要出多少个数

思路:设Si为小于i的整个区间需要出的个数,则有,S(b + 1) - S(a) >= c,为了保证整张图是一个连通图,加上隐含的S(i + 1) - Si >= 0,S(i + 1) - Si <= 1.

于是一个查分约束系统建成,最后求最小值的解,跑一遍最短路,题目保证了不会存在没有最短路情况。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int maxn = 2e5 + 5;int n, s, t;int a, b, c;int head[maxn];int dis[maxn];bool vis[maxn];struct{    int to;    int cost;    int next;}node[maxn];void add(int a, int b, int c, int i){        node[i].to = b;        node[i].cost = c;        node[i].next = head[a];        head[a] = i;}void spfa(){    memset(vis, 0, sizeof(vis));    for(int i = s; i <= t; i++) dis[i] = -maxn;        dis[s] = 0;    queue<int> Q;    Q.push(s);    vis[s] = 1;    while(!Q.empty())    {        int cur = Q.front();        Q.pop();        vis[cur] = 0;        for(int i = head[cur]; i != -1; i = node[i].next)        {                int tmp = node[i].to;                int cost = node[i].cost;                if(dis[tmp] < dis[cur] + cost)                {                    dis[tmp] = dis[cur] + cost;                    if(!vis[tmp])                    {                        Q.push(tmp);                        vis[tmp] = 1;                    }                }        }    }    cout << dis[t] << endl;}int main(){    while(cin >> n)    {        s = maxn, t = 0;        memset(head, -1, sizeof(head));        for(int i = 0; i < n; i++)        {            scanf("%d %d %d", &a, &b, &c);            add(a, b + 1, c, i);            s = min(s, a);            t = max(t, b + 1);        }        int m = n;        for(int i = s; i <= t; i++)        {            add(i, i + 1, 0, m++);            add(i + 1, i, -1, m++);        }        spfa();    }    return 0;}