POJ1201 区间
题目大意:
给定n个整数区间[ai,bi]和n个整数ci,求一个最小集合Z,满足|Z∩[ai,bi]|>=ci(Z里边在闭区间[ai,bi]的个数不小于ci)。
多组数据:
n(1<=n<=50000)区间的个数
n行:
ai bi ci(0<=ai<=bi<=50000,1<=ci<=bi-ai+1)
_____________________________________________________
这是一道查分约束题目。
Si为0-i中包含在Z中的个数,固有:
Si-Si-1<=1
Si-Si-1>=0
Sbi-Sai-1>=ci
依照上面不等式,变形并建边。
求的Smax-S0>=x,变形为S0-Smax<=-x,所以求max到0的最短路,就是答案的相反数。
_____________________________________________________
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 int n,maxd; 9 struct edge 10 { 11 int u,v,w,next; 12 }e[150010]; 13 int head[50010],js=0; 14 int dis[50010]; 15 bool inq[50010]; 16 int inqt[50010]; 17 queue<int>q; 18 void init() 19 { 20 js=0; 21 maxd=0; 22 memset(head,0,sizeof(head)); 23 } 24 void addage(int u,int v,int w) 25 { 26 e[++js].u=u;e[js].v=v;e[js].w=w; 27 e[js].next=head[u];head[u]=js; 28 } 29 bool spfa() 30 { 31 memset(inq,0,sizeof(inq)); 32 memset(dis,0x7f,sizeof(dis)); 33 memset(inqt,0,sizeof(inqt)); 34 q.push(maxd+1); 35 inq[maxd+1]=1; 36 inqt[maxd+1]=1; 37 dis[maxd+1]=0; 38 while(!q.empty()) 39 { 40 int u=q.front(); 41 q.pop(); 42 inq[u]=0; 43 for(int i=head[u];i;i=e[i].next) 44 { 45 int v=e[i].v; 46 if(dis[v]>dis[u]+e[i].w) 47 { 48 dis[v]=dis[u]+e[i].w; 49 if(!inq[v]) 50 { 51 inq[v]=1; 52 inqt[v]++; 53 q.push(v); 54 if(inqt[v]>50000)return 0; 55 } 56 } 57 } 58 } 59 return 1; 60 } 61 int main() 62 { 63 while(scanf("%d",&n)==1) 64 { 65 init(); 66 for(int a,b,c,i=1;i<=n;i++) 67 { 68 scanf("%d%d%d",&a,&b,&c); 69 if(b>maxd)maxd=b; 70 addage(b+1,a,-c); 71 } 72 73 for(int i=1;i<=maxd+1;i++) 74 { 75 addage(i-1,i,1); 76 addage(i,i-1,0); 77 } 78 if(spfa())printf("%d\n",-dis[0]); 79 } 80 return 0; 81 }