poj1201 Intervals——差分约束

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

差分约束裸题;

设 s[i] 表示到 i 选了数的个数前缀和;

根据题意,可以建立以下三个限制关系:

s[bi] >= s[ai-1] + ci ( 1 <= i <= n)

s[i] >= s[i-1] + 0 ( 1 <= i <= mx)

s[i-1] >= s[i] + (-1) (1 <= i <= mx)

然后求最长路,可以发现其中的 dis 值不会多余增大,也就满足题意要求的最小集合条件;

1A了好开心!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int const maxn=50005;
int n,hd[maxn],ct,dis[maxn],mx;
bool vis[maxn];
queue<int>q;
struct N{
    int to,nxt,w;
    N(int t=0,int n=0,int w=0):to(t),nxt(n),w(w) {}
}ed[maxn*3];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
void spfa()
{
    memset(dis,-3,sizeof dis);
    dis[0]=0; vis[0]=1; q.push(0);
    while(q.size())
    {
        int x=q.front(); q.pop(); vis[x]=0;
        for(int i=hd[x];i;i=ed[i].nxt)
        {
            int u=ed[i].to;
            if(dis[u]<dis[x]+ed[i].w)
            {
                dis[u]=dis[x]+ed[i].w;
                if(!vis[u])vis[u]=1,q.push(u);
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1,a,b,c;i<=n;i++)
    {
        scanf("%d%d%d",&a,&b,&c); if(a>b)swap(a,b);
        mx=max(mx,max(a,b));
        add(a-1,b,c);
    }
    mx=max(mx,n);
    for(int i=1;i<=mx;i++)//
    {
         add(i-1,i,0); add(i,i-1,-1);
    }
    spfa();
    printf("%d",dis[mx]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Zinn/p/9278421.html