POJ1201 Intervals

这道题,emm裸的差分约束,我们不妨定义s[i]表示0~i最少选多少个数,那么由题意给的ai~bi不少于ci个,因为[ai~bi]是闭区间,那么我们就可以列出来s[bi]-s[ai-1]>=ci,这样一个差分约束的框架就形成了,但是不能保证结果,所以我们要再附加一些条件1.s[i]-s[i-1]<=1,s[i]-s[i-1]>=0,然后我们就可以愉快的跑一下单源最长路,输出结果就好了(dis[maxa]]我们要记录区间的最左和最右)

代码(2000ms 卡过)

//By AcerMo
#include<cmath>
#include<queue> 
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;
int n,maxn,minn,m;
struct edge
{
	int v,len;
}now;
vector<edge>v[51001];
bool vis[51001];
int dis[51001];
inline void SPFA()
{
	queue<int>q;q.push(minn-1);
    vis[minn-1]=1,dis[minn-1]=0;
    while(!q.empty())
    {
        int u=q.front();q.pop();vis[u]=0;
        for(int j=0;j<v[u].size();j++)
        {
            int go=v[u][j].v;
            int pay=v[u][j].len;
            if(dis[go]<dis[u]+pay)
            {
                dis[go]=dis[u]+pay;
                if(!vis[go])
                	vis[go]=1,q.push(go); 
            }
        }
    }
    return (void)(printf("%d\n",dis[maxn]));
}
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x; 
} 
inline void add(int a,int b,int c)
{
	now.v=b;now.len=c;v[a].push_back(now);
	return ;
}
int main()
{
	for (int i=0;i<=50001;i++) dis[i]=-INF;
    while(scanf("%d",&m)!=EOF)
    {
        minn=INF,maxn=0;
        for (int i=1;i<=m;i++)
        {
            int u=read(),x=read(),len=read();
            maxn=max(maxn,x);minn=min(minn,u);
            add(u-1,x,len);
        }
        for(int i=minn;i<=maxn;i++)
            add(i,i-1,-1),add(i-1,i,0);
        SPFA();
        for(int i=0;i<=maxn;i++) 
			v[i].clear(),dis[i]=-INF;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80965043