POJ 1201 (差分约束求最短路)

根据题意得出约束条件:
s[bi]-s[ai-1] >= ci

变形可得 s[ai-1] -s[bi]<= - ci

这是显然的。

另外不要忘了对于一个连续的整数集合,它包含隐性条件
0<=s[i]-s[i-1] <= 1
 

综上可得:
①s[ai-1]-s[bi] <= -ci
②s[i]-s[i-1] <= 1
③s[i-1]-s[i] <= 0

最后转化为最短路问题

 /*
 qq:1239198605
 ctgu_yyf
        */

#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 999999 
#define ll long long
using namespace std;

struct Edge{
	int s,t,w;
};

Edge edge[50002];
int dis[50002],ma,mi,n;

void bellman()
{
	bool flag=true;
	while(flag)
	{
		flag=false;
		
		//因为要维持 一个差分约束系统 对于一个连续的集合 所以应该满足的条件有
		//1  s[bi]-s[ai-1]>=w
		//2  0<=s[i]-s[i-1]<=1 
		
		for(int i=1;i<=n;i++)
		if(dis[edge[i].t]>dis[edge[i].s]-edge[i].w)
		{
		
		dis[edge[i].t]=dis[edge[i].s]-edge[i].w;
		flag=true;
	    }
	    
	    //隐性条件判定 
	    for(int i=mi;i<=ma;i++)
	    if(dis[i]-dis[i-1]>1)
	    {
		dis[i]=dis[i-1]+1;
		flag=true;
	    }
	    
	    for(int i=ma;i>=mi;i--)
	    if(dis[i-1]>dis[i])
	    {
	    	dis[i-1]=dis[i];
	    	flag=true;
		}
	}
		
}

int main()
{
   ios::sync_with_stdio(false);
   
   while(cin>>n)
   {
   
   ma=-1;
   mi=inf;
   
   
   
   for(int i=1;i<=n;i++)
   {
   
   cin>>edge[i].t>>edge[i].s>>edge[i].w;
   
  
   ma=max(ma,edge[i].s);
   mi=min(mi,edge[i].t);
   edge[i].t--;
}

   for(int i=0;i<=ma;i++)
   dis[i]=0; 

   bellman();
   
   cout<<dis[ma]-dis[mi-1]<<endl;
}

return 0;
}

第一个式子在代码中化简得到的是dis[edge[i].t]<=dis[edge[i].s]-edge[i].w

因为要时刻满足这个条件 所以当他不满足的时候 需要更新它

用if(dis[edge[i].t]>dis[edge[i].s]-edge[i].w)

来判断 大于就让它取等 

下面同理。

猜你喜欢

转载自blog.csdn.net/k_koris/article/details/81412588