鄙人第一个差分约束系统。
看了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;
}
本文详细介绍了使用贝尔曼-福特算法解决差分约束系统问题的方法,并通过实例展示了如何优化代码以避免超时错误。文章还探讨了如何通过调整约束条件来求得满足条件的最小和最大值。
897

被折叠的 条评论
为什么被折叠?



