【POJ1021】Intervals (最短路解差分约束)
题目:
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
题意:
我们选数,每个数只能选一次。给定n个条件[ai,bi]和ci,表示区间[ai,bi]中至少选ci个数,问一共最少选多少个数。
分析:
设xi为小于等于i的数中选了多少个数。对于条件[ai,bi]、ci,我们有bi-ai-1>=ci,是差分约束系统,可以用最短路求解。
另外,题目中有比较隐蔽的条件:每个数只能选一个,一个数选的次数也不能为负,那么就是说对于相邻的两个数x、y,有0<=y-x<=1,要根据这个条件建边才能保证答案无误。
最后输出Xmx-Xmn。(差分约束系统要不无解,要不有无数解,因为一旦有解只要保证他们之间差值不变即可。题目问一共最少选多少个数,而xi的最小值为0,所以答案为Xmx-Xmn)
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 50010 9 #define INF 0xfffffff 10 11 struct node 12 { 13 int x,y,c,next; 14 }t[Maxn*4];int len=0; 15 16 int first[Maxn],cnt[Maxn],dis[Maxn]; 17 bool bq[Maxn],inq[Maxn]; 18 19 int mymin(int x,int y) {return x<y?x:y;} 20 int mymax(int x,int y) {return x>y?x:y;} 21 22 void ins(int x,int y,int c) 23 { 24 t[++len].x=x;t[len].y=y;t[len].c=c; 25 t[len].next=first[x];first[x]=len; 26 } 27 28 queue<int > q; 29 30 void spfa(int s) 31 { 32 memset(dis,63,sizeof(dis)); 33 memset(inq,0,sizeof(inq)); 34 memset(cnt,0,sizeof(cnt)); 35 if(!q.empty()) q.pop(); 36 dis[s]=0;inq[s]=1;q.push(s); 37 while(!q.empty()) 38 { 39 int x=q.front();q.pop();inq[x]=0; 40 for(int i=first[x];i;i=t[i].next) 41 { 42 int y=t[i].y; 43 if(dis[y]>dis[x]+t[i].c) 44 { 45 dis[y]=dis[x]+t[i].c; 46 if(!inq[y]) 47 { 48 q.push(y); 49 inq[y]=1; 50 } 51 } 52 } 53 } 54 } 55 56 int main() 57 { 58 int m,mx=0,mn=INF; 59 scanf("%d",&m); 60 memset(first,0,sizeof(first)); 61 memset(bq,0,sizeof(bq)); 62 for(int i=1;i<=m;i++) 63 { 64 int x,y,c; 65 scanf("%d%d%d",&x,&y,&c);x++;y++; 66 ins(y,x-1,-c); 67 bq[x]=bq[y]=1; 68 mx=mymax(mx,y);mn=mymin(mn,x-1); 69 } 70 for(int i=mn;i<mx;i++) ins(i+1,i,0); 71 for(int i=mn;i<mx;i++) ins(i,i+1,1); 72 for(int i=mn;i<=mx;i++) ins(mx+1,i,0); 73 spfa(mx+1); 74 //for(int i=mn;i<=mx;i++) printf("%d %d\n",i,dis[i]); 75 printf("%d\n",dis[mx]-dis[mn]); 76 return 0; 77 }
感觉自己考虑问题总是不全面啊。
2016-04-10 16:31:30