题意:
有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai,bi]这个区间的整数至少有ci个。如果存在这样的序列,请求出满足题目要求的最短的序列长度是多少。
分析:
dis[i]表示从0->i-1这i个数存在多少个数。
则有dis[b+1]-dis[a]>=c;
dis[i+1]-dis[i]>=0 && dis[i+1]-dis[i]<=1
转换成为:
dis[a]-dis[b+1]<=-c;
dis[i]-dis[i+1]<=0
dis[i+1]-dis[i]<=1
建图。dis[en]-dis[st]<=w.
#include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=5e4+100; struct Edge{ int from,to; int dist; }; struct BellmanFord{ int n,m; vector<Edge>edges; vector<int>G[MAXN]; bool inq[MAXN]; int d[MAXN]; int p[MAXN]; int cnt[MAXN]; void init(int n) { this->n=n; for(int i=0;i<n;i++)G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int dist) { edges.push_back((Edge){from,to,dist}); m=edges.size(); G[from].push_back(m-1); } bool negativeCycle() { queue<int>Q; memset(inq,0,sizeof(inq)); memset(cnt,0,sizeof(cnt)); for(int i=0;i<n;i++) { d[i]=0;inq[0]=true;Q.push(i); } while(!Q.empty()) { int u=Q.front();Q.pop(); inq[u]=false; for(int i=0;i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=G[u][i]; if(!inq[e.to]) { Q.push(e.to); inq[e.to]=true; if(++cnt[e.to]>n) return true; } } } } return false; } }; BellmanFord solver; int main() { int n; while(~scanf("%d",&n)) { int maxn=0; int minn=INF; int a,b,c; solver.init(MAXN-10); for(int i=0;i<n;i++) { scanf("%d%d%d",&a,&b,&c); maxn=max(maxn,b+1); minn=min(minn,a); solver.AddEdge(b+1,a,-c); } for(int i=0;i<=maxn-1;i++){ solver.AddEdge(i+1,i,0); solver.AddEdge(i,i+1,1); } solver.negativeCycle(); printf("%d ",solver.d[maxn]-solver.d[minn]); } return 0; }