【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 }
[POJ1201]

 

感觉自己考虑问题总是不全面啊。

 

2016-04-10 16:31:30

posted @ 2016-04-10 16:30  konjak魔芋  阅读(306)  评论(0编辑  收藏  举报