对应POJ题目:点击打开链接
Description
Input
Output
Sample Input
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
思路:差分约束系统;设0~i中有S[i]个元素属于集合,那例子就可以表示为:
S[7] - S[2] >= 3
S[10] - S[7] >= 3
S[8] - S[5] >= 1
S[3] - S[0] >= 1
S[11] - S[9] >= 1
则此题的答案就是求S[max] - S[min-1],即是以最大元素为起点,最小元素为终点的最长路。。。
此外还有一些隐含条件:0 <= S[i+1] - S[i] <=1
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> using namespace std; const int MAXN=160000+10; const int INF=1<<30; int n,m,mm,num; int dis[50020]; int head[50020]; int vis[50020]; int minn=INF,maxn=0; struct edge { int v,w,next; }E[MAXN]; void buildmap(int u, int v, int w) { E[num].v=v; E[num].w=w; E[num].next=head[u]; head[u]=num++; } void spfa() { memset(vis, 0, sizeof(vis)); for(int i=minn; i<=maxn; i++) dis[i]=-INF; dis[maxn]=0; vis[maxn]=1; queue<int>q; q.push(maxn); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=E[i].next){ int v=E[i].v; if(dis[u]+E[i].w > dis[v]){ dis[v] = dis[u]+E[i].w; if(!vis[v]){ vis[v]=1; q.push(v); } } } } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d", &n)==1) { memset(head, -1, sizeof(head)); num=0; int i,j; minn=INF, maxn=0; for(i=0; i<n; i++){ int u,v,w; scanf("%d%d%d", &v,&u,&w); u++; if(v<minn) minn=v; if(u>maxn) maxn=u; buildmap(u,v,w); } for(i=minn; i<maxn; i++){ buildmap(i+1,i,0); buildmap(i,i+1,-1); } spfa(); printf("%d\n", dis[minn]); } }