題目: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; }