/* 给你 n 个区间 [Ai, Bi],要求从每一个区间中至少选出 Ci 个数出来组成一个序列 问:满足上面条件的序列的最短长度是多少? 则对于 不等式 f(b)-f(a)>=c,建立 一条 b 到 a 的边 权值为 c,则求的最长路 即为 最小值(集合) 而且有隐含条件:0<=f(a)-f(a-1)<=1 则有边权关系(a,a-1,0)以及(a-1,a,-1); */ /* 一般地,差分约束系统分两类:求最大差和最小差 1、求最大差 建立形如 A-B<=C 的不等式。在原图中加入边 <B, A> 边权为 C 对建好的图跑最短路,假设存在负环,无解(推断条件为某点被更新了 n 次)。n 为图中点的数量 2、求最小差 建立形如 A-B>=C 的不等式,在原图中加入边 <B, A> 边权为 C 对建好的图跑最长路,假设存在正环,无解(推断条件为某点被更新了 n 次),n 为图中点的数 */ # include<stdio.h> # include<algorithm> # include<string.h> # include<queue> # include<stack> # define MAX 50010 const int INF=0x3fffff; using namespace std; int tot; int head[MAX];///头节点数组 int vis[MAX]; int dis[MAX]; int minn,maxx; struct node { int u; int v; int val; int next; } Edge[MAX<<2]; void addEdge(int u,int v,int val) { Edge[tot].u=u; Edge[tot].v=v; Edge[tot].val=val; Edge[tot].next=head[u]; head[u]=tot++; } void Spfa() { for(int i=minn; i<=maxx; i++) dis[i]=-INF; queue<int>q; dis[minn]=0; vis[minn]=1; q.push(minn); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=Edge[i].next) { int v=Edge[i].v; if(dis[v]<dis[u]+Edge[i].val) { dis[v]=dis[u]+Edge[i].val; if(!vis[v]) { vis[v]=1; q.push(v); } } } } printf("%d\n",dis[maxx]); return ; } int main() { int n,a,b,c; while(~scanf("%d",&n)) { tot=0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); maxx=0; minn=50010; for(int i=0; i<n; i++) { scanf("%d%d%d",&a,&b,&c); b++; if(maxx<b) maxx=b; if(minn>a) minn=a; addEdge(a,b,c); } for(int i=minn; i<maxx; i++) ///隐含边 { addEdge(i,i+1,0); addEdge(i+1,i,-1); } Spfa(); } return 0; }
时间: 2024-10-01 03:05:24