POJ-1201 Intervals(差分 最小值最长路)

Intervals

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 30103   Accepted: 11643

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

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cstring>
    using namespace std;
	const int INF=0x3f3f3f3f;
	const int MAXN=500100;
	const int MAXM=MAXN*5;
	#define INF 0x3f3f3f3f
	struct Node
	{
	    int to;
	    int w;
	};
	vector<Node> G[MAXM];
	bool vis[MAXN];
	int visitcount[MAXN];
	queue <int> q;
	int dis[MAXN];
	void init(int n)
	{
	    int i;
	    for(i=0;i<=n;i++)
	    G[i].clear();
	}
	void addedge(int u,int v,int w)
	{
	    Node t={v,w};
	    G[u].push_back(t);
	}
	bool spfa(int s,int n)//单源最短路(s为起点,n为节点总数)
	{
	    int u;
	    for(int i=s;i<=s+n-1;i++)
	    dis[i]=INF;
	    memset(vis,0,sizeof(vis));
        memset(visitcount,0,sizeof(visitcount));
	    while(!q.empty())
	    q.pop();
	    q.push(s);
	    vis[s]=true;
	    dis[s]=0;
	    while (!q.empty())
	    {
	        u=q.front();
	        q.pop();
	        vis[u]=false;
	        if(visitcount[u]++>n)
	        return true;     //return true说明有负权圈
	        for(int i=0;i<G[u].size();i++)
	        {
	            int v=G[u][i].to;
	            int w=G[u][i].w;
	            if (dis[v]>dis[u]+w)
	            {
	                dis[v]=dis[u]+w;
	                if (!vis[v])
	                {
	                    vis[v]=true;
	                    q.push(v);
	                }
	            }
	        }
	    }
	    return false;
	}
int main()
{
    int n;
    int i;
    int u,v,w;
    scanf("%d",&n);
    int minn=INF,maxn=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        u+=1;
        v+=1;
        minn=min(minn,u);
        maxn=max(maxn,v);
        addedge(u-1,v,-w);
    }
    for(i=minn;i<=maxn;i++)
    {
         addedge(i-1,i,0);
         addedge(i,i-1,-1*(-1)); //因为添的都是负权边
    }
    if(!spfa(minn-1,maxn-minn+2))
    {
       printf("%d\n",-dis[maxn]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xigongdali/article/details/81868001
今日推荐