poj1201 Intervals——差分約束

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

差分約束裸題;ide

設 s[i] 表示到 i 選了數的個數前綴和;spa

根據題意,能夠創建如下三個限制關係:ci

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

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

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

而後求最長路,能夠發現其中的 dis 值不會多餘增大,也就知足題意要求的最小集合條件;io

1A了好開心!class

代碼以下:stream

#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;
}
相關文章
相關標籤/搜索