题目链接:传送门
题目大意:给定n个区间[ai,bi],这n个区间中对应的每个区间至少要有ci个数,求满足这些条件最少需要的数
解题思路:差分约束,写出约束方程,将每个数看成一个点,建图,求最长路
对于第i个区间:D[bi]-D[ai-1]>=ci
隐藏的条件:D[i]-D[i-1]>=0,D[i]-D[i-1]<=1(D[i-1]>=D[i]-1)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<algorithm> #include<stack> #include<queue> using namespace std; typedef long long ll; typedef pair<int,int>PA; const int N = 50005; const int M = 1000; const int INF = 0x3fffffff; const int mod = 1e9+7; struct Edge{ int node,len; Edge*next; }m_edge[N*10]; Edge*head[N]; int Ecnt,vis[N],dist[N]; void init() { Ecnt = 0; fill( head , head+N , (Edge*)0 ); } void mkEdge( int a , int b , int c ) { m_edge[Ecnt].node = b; m_edge[Ecnt].len = c; m_edge[Ecnt].next = head[a]; head[a] = m_edge+Ecnt++; } void spfa( int n ) { fill( vis , vis+N , 0 ); fill( dist , dist+N , -INF ); queue<int>point; vis[n] = 1; dist[n] = 0; point.push(n); while( !point.empty() ){ int s = point.front(); point.pop(); vis[s] = 0; for( Edge*p = head[s] ; p ; p = p->next ){ int t = p->node; if( dist[t] < dist[s]+p->len ){ dist[t] = dist[s]+p->len; if( !vis[t] ){ vis[t] = 1; point.push(t); } } } } } int main() { int n; while( cin >> n ){ init(); int a,b,c,mx = 0; for( int i = 0 ; i < n ; ++i ){ cin >> a >> b >> c; mx = max(mx,b); mkEdge( a-1 , b , c ); } for( int i = 1 ; i <= mx ; ++i ){ mkEdge( i-1 , i , 0 ); mkEdge( i , i-1 , -1 ); } spfa(0); cout << dist[mx] << endl; } return 0; }