鄙人第一个差分约束系统。
看了N多的资料和别人的解题报告,发现下面用BELLMAN FORD 加稍微的剪枝时间可以飙到200MS以内,不错不错。
就是那个FLAG,没了这个就TLE了。。。惨剧啊!!!!
另外的话,这个题目的例子是给了5个区间,说5个区间包含了Z数组C个数,接着问你Z数组到底至少有几个数。数组不用连续
主要是下面三点
1。s[b]>=s[a-1]+c
2.s[b-1]>=s[b]+(-1)
3.s[b]>=s[b-1]
维护这三个不等式即可,s[]表示从0到x含有的数字的个数
如何维护呢?
想像一下做图论的时候题目对边的更新。对了!
那个更新和第一个不等式是相似的。
注意这种题目使不能用DISTRA算法做的,因为C可能为负值。对应就是不等式可能无解。所以要用BELLMAN FORD。另外对于SPFA,现在还没写,下次写的时候会SHARE
还有就是很神奇的就是。如果维护上面第一个不等式,我们得到的解是满足约束的最小值!
那么怎么得到最大值呢?!
很简单,用小于等于!
哇哈好!
#include<stdio.h>
struct EDGE
{
int x,y,v;
}edge[50005];
const int MAXN=1<<30-1;
int n,rmin,rmax,dis[50005];
void bellman()
{
for(int i=rmin;i<=rmax;i++) dis[i]=-MAXN;
dis[rmin]=0;
for(int i=0;i<rmax-rmin;i++)
{
bool flag=false;//剪枝
for(int j=0;j<n;j++)
if(dis[edge[j].x]!=-MAXN&&dis[edge[j].y]<dis[edge[j].x]+edge[j].v)//求最小值
{
dis[edge[j].y]=dis[edge[j].x]+edge[j].v;
flag=true;
}
for(int j=rmin;j<rmax;j++)
if(dis[j]!=-MAXN&&dis[j+1]<dis[j])
{
dis[j+1]=dis[j];
flag=true;
}
for(int j=rmax;j>rmin;j--)
if(dis[j]!=-MAXN&&dis[j-1]<dis[j]-1)
{
dis[j-1]=dis[j]-1;
flag=true;
}
if(!flag) break;
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
rmin=MAXN;
rmax=-1;
for(int i=0;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
b++;
edge[i].x=a;
edge[i].y=b;
edge[i].v=c;
if(a<rmin) rmin=a;
if(b>rmax) rmax=b;
}
bellman();
printf("%d/n",dis[rmax]);
}
return 0;
}
并且由于另外两个不等式只和点有关,如果我都把他们构造成了边,那么就TLE了,看来SPFA还是稳定很多啊
#include<stdio.h>
const int E=50005;
const int V=50005;
const int INF=1<<25-1;
struct EDGE
{
int u,v,val;
}edge[E*4];
int e,rmin,rmax,dist[V];
void addedge(int a,int b,int c)
{
edge[e].u=a;
edge[e].v=b;
edge[e++].val=c;
}
int bellman()
{
for(int i=rmin;i<=rmax;i++) dist[i]=-INF;
dist[rmin]=0;
//for(int i=rmin;i<=rmax;i++)
for(int i=0;i<rmax-rmin;i++)
{
bool flag=false;
for(int j=0;j<e;j++)
if(dist[edge[j].u]!=-INF&&dist[edge[j].v]<dist[edge[j].u]+edge[j].val)
{
dist[edge[j].v]=dist[edge[j].u]+edge[j].val;
flag=true;
}
if(!flag) break;
}
return dist[rmax]-dist[rmin];
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
e=0;
rmin=INF;
rmax=-1;
for(int i=1;i<=n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
b++;
if(a<rmin) rmin=a;;
if(b>rmax) rmax=b;
addedge(a,b,c);
}
for(int i=rmin+1;i<=rmax;i++)
{
addedge(i-1,i,0);
addedge(i,i-1,-1);
}
printf("%d/n",bellman());
}
return 0;
}