[POJ-1201]Intervals

题目传送门

差分约束系统很棒的应用,首先运用前缀和的思想,令s[k]为0~k中被选出来数的个数,则s[b[i]]>=s[a[i]-1]+c,这样会有一个问题,那就是下标可能会出现负数,因此我们可以改变前缀和表示的方法,设s[k]为0~k-1中被选出来的数,则约束条件可以转化为:s[b[i]+1]-s[a[i]]>=c;简单处理后可得到s[b[i]+1]>=s[a[i]+c;但是只有这一个约束条件远远不够,这只是数据硬性规定的,而还有一些条件是隐含的,有下面两种隐含条件也需要加入约束系统:1)s[k]是前缀和的形式,所以s[k]不可能比s[k-1]小,可得到s[k]>=s[k-1]+0;(2)s[k]最多比s[k-1]多选k这一个数,所以s[k]<=s[k-1]+1,简单处理后得到s[k-1]>=s[k]-1,加入以上两种边后SPFA跑最长路求解即可

下面给出参考代码:

 

 1 #include<iostream>
 2 #include<queue>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 int t,n,a,b,c,v[550005],w[550005],head[550005],nxt[550005],cnt,dist[500005],maxn;
 7 bool vis[500005];
 8 void add(int a,int b,int c)
 9 {
10     v[++cnt]=b;
11     w[cnt]=c;
12     nxt[cnt]=head[a];
13     head[a]=cnt;
14 }
15 void spfa(int node)
16 {
17     queue<int>q;
18     q.push(node);
19     vis[node]=1;
20     while(!q.empty())
21     {
22         int c=q.front();
23         q.pop();
24         vis[c]=0;
25         for(int i=head[c];i;i=nxt[i])
26         {
27             int y=v[i];
28             if(dist[y]<dist[c]+w[i])
29             {
30                 dist[y]=dist[c]+w[i];
31                 if(!vis[y])
32                 {
33                     q.push(y);
34                     vis[y]=1;
35                 }
36             }
37         }
38     }
39 }
40 int main()
41 {
42     scanf("%d\n",&t); 
43     while(t--)
44     {
45         scanf("%d\n",&n);
46         memset(v,0,sizeof(v));
47         memset(w,0,sizeof(w));
48         memset(head,0,sizeof(head));
49         memset(nxt,0,sizeof(nxt));
50         cnt=0;maxn=-21374404;
51         for(int i=1;i<=n;i++)
52         {
53             scanf("%d%d%d",&a,&b,&c);
54             //dist[b+1]>=c+dist[a]
55             add(a,b+1,c);
56             maxn=max(maxn,b+1);
57         }
58         for(int i=1;i<=maxn;i++)
59         {
60             //dist[i]>=0+dist[i-1]
61             add(i-1,i,0);
62             //dist[i-1]>=dist[i]-1
63             add(i,i-1,-1);
64         }
65         for(int i=1;i<=maxn;i++)
66         {
67             dist[i]=-21374404;
68             add(0,i,0);
69         }
70         spfa(0);
71         printf("%d",dist[maxn]);
72         if(t>0)printf("\n");
73     }
74     return 0;
75 } 
View Code

 

posted @ 2019-06-25 20:35  shao0320  阅读(156)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************