| Time Limit: 2000MS | Memory Limit: 65536K | |
| Total Submissions: 20779 | Accepted: 7863 |
Description
Input
Output
Sample Input
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
Source
题目大意:
n行,每行a,b,c,表示在区间a,b内要找c个数,问你总共至少要找多少个数?
解题思路:
差分约束系统。
在本题中,如果[a,b]中要找c个元素,那么:s[b]-s[a-1]>=c,我们可以推得:s[a-1] - s[b] <= -c
同时,由于每一个值上最多只能含有一个元素,那么:s[i] - s[i-1]<=1 ,又由于s[i] - s[i-1]>=0 推得:s[i-1] - s[i] <=0
这样:我们有了三个约束不等式:
s[a-1] - s[b] <= -c
s[i] - s[i-1]<=1
s[i-1] - s[i] <=0
于是:如果起点为from,重点为to,我们只要求出:s[to] -s[from-1] >= M就可以了,因此求出 s[from-1]-s[to]<=-M,即求to 到 from-1 的最短路径,
注意:由于i<0,所以i-1可能小于0,因此全部向右平移1位。
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
const int maxn=50000;
const int inf=0x3f3f3f3f;
struct edge{
int u,v,w,next;
}e[maxn*10];
int head[maxn*2+10],dist[maxn*2+10],cnt;
int n,from,to;
void initial(){
cnt=0;
from=inf,to=0;
for(int i=0;i<=maxn;i++) head[i]=-1;
}
void adde(int u,int v,int w){
u++;v++;
e[cnt].u=u,e[cnt].v=v,e[cnt].w=w,e[cnt].next=head[u],head[u]=cnt++;
}
void input(){
int u,v,w;
//[v]-[u-1]>=w [u-1]-[v]<=-w
for(int i=0;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
adde(v,u-1,-w);
if(u<from) from=u;
if(v>to) to=v;
}
//0<=[i]-[i-1]<=1
for(int i=from;i<=to;i++){
adde(i-1,i,1);
adde(i,i-1,0);
}
}
bool spfa(int from){
int s=from,num[maxn];
bool visited[maxn];
for(int i=0;i<=maxn;i++){
num[i]=0;
dist[i]=inf;
visited[i]=false;
}
queue <int> q;
q.push(s);
visited[s]=true;
dist[s]=0;
while(!q.empty()){
s=q.front();
q.pop();
for(int i=head[s];i!=-1;i=e[i].next){
int d=e[i].v;
if(dist[d]>dist[s]+e[i].w){
dist[d]=dist[s]+e[i].w;
if(!visited[d]){
visited[d]=true;
q.push(d);
num[d]++;
if(num[d]>n) return false;
}
}
}
visited[s]=false;
}
return true;
}
void solve(){
//get [to]-[from-1]>=M; [from-1]-[to]<=-M
spfa(to+1);
cout<<-dist[from]<<endl;
}
int main(){
while(scanf("%d",&n)!=EOF){
initial();
input();
solve();
}
return 0;
}
POJ 1201 Intervals(图论-差分约束),布布扣,bubuko.com
原文:http://blog.csdn.net/a1061747415/article/details/31806111