1. 程式人生 > >poj1201(差分約束)

poj1201(差分約束)

blank pri amp tro oid spfa while 所有 sin

題很水。。。但我被坑慘了

。。。。。。。。

。。。。。.。。。。。

。。。。。。。

構成差分約束系統時,1.如果在所有點外添加一個超級源0號點,並使得超級源到所有其他點的距離為0,那麽最終求出的0號點到其他所有原始點的最短距離就是本系統的一個可行解,且可行解之間的差距最小. 2.如果初始時不添加超級源,只是將原始點的初始距離設為INF,且令其中一個原始點的初始距離為0,然後求該點到其他所有點的最短距離,那麽最短距離的集合就是一個可行解,且該可行解兩兩之間的差距最大.註意方案2只能在該問題一定存在解的時候即肯定不存在負權環的時候用.否則從1號點到其他點沒有路,但是其他點的強連通分量中有負權環,這樣根本探測不到錯誤

) 所以我們需要采取方案1.

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int maxn=50000+10;
const int maxm=500000+10;
const int nil=1e9;

struct my{
       int next;
       int v;
       int w;
};

queue<int>Q;
int maxx=-1;
int adj[maxn],fa,n,m,d[maxn],inq[maxn];
my bian[maxm];

void myinsert(int u,int v,int w){ bian[++fa].v=v; bian[fa].next=adj[u]; bian[fa].w=w; adj[u]=fa; } int spfa(int s){ for (int i=0;i<=maxx;i++) d[i]=nil; d[s]=0; Q.push(s); inq[s]=true; while(!Q.empty()){ int u=Q.front();Q.pop(); inq[u]=false;
for (int i=adj[u];i!=-1;i=bian[i].next){ int v=bian[i].v; if(d[v]>d[u]+bian[i].w){ d[v]=d[u]+bian[i].w; if(!inq[v]){ Q.push(v); inq[v]=true; } } } } return d[maxx]-d[9]; } int main(){ memset(adj,-1,sizeof(adj)); memset(bian,-1,sizeof(bian)); scanf("%d",&m); int u,v,w; for (int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); u+=10; v+=10; maxx=max(maxx,v); myinsert(v,u-1,-w); } for (int i=10;i<=maxx;i++){ myinsert(i,i-1,0); myinsert(i-1,i,1); myinsert(0,i,0); } myinsert(0,9,0); printf("%d\n",spfa(0)); return 0; }

poj1201(差分約束)