1. 程式人生 > >POJ1201Intervals(差分約束系統)

POJ1201Intervals(差分約束系統)

多少 esp namespace 沒有 ios int tdi bsp ron

題目說[ai, bi]區間內和點集Z至少有ci個共同元素,那也就是說如果我用Si表示區間[0,i]區間內至少有多少個元素的話,

那麽Sbi - Sai >= ci,這樣我們就構造出來了一系列邊,權值為ci,但是這遠遠不夠,因為有很多點依然沒有相連接起來

(也就是從起點可能根本就還沒有到終點的路線),此時,我們再看看Si的定義,也不難寫出0<=Si - Si-1<=1的限制條

件,雖然看上去是沒有什麽意義的條件,但是如果你也把它構造出一系列的邊的話,這樣從起點到終點的最短路也就

順理成章的出現了。

還是嚴格按照差分的意思來解題。

 1 #include<cstring>
 2
#include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<queue> 7 #define N 50007 8 #define INF 2000000009 9 using namespace std; 10 11 int n,S,T; 12 int dis[N],ins[N]; 13 int cnt,head[N],Next[N*4],rea[N*4],val[N*4]; 14 15 void add(int u,int
v,int fee) 16 { 17 Next[++cnt]=head[u]; 18 head[u]=cnt; 19 rea[cnt]=v; 20 val[cnt]=fee; 21 } 22 void Spfa() 23 { 24 for (int i=0;i<=S;i++) 25 dis[i]=-INF,ins[i]=0; 26 queue<int>q; 27 q.push(S);ins[S]=1;dis[S]=0; 28 while(!q.empty()) 29 { 30 int
u=q.front();q.pop(); 31 for (int i=head[u];i!=-1;i=Next[i]) 32 { 33 int v=rea[i],fee=val[i]; 34 if (dis[v]<dis[u]+fee) 35 { 36 dis[v]=dis[u]+fee; 37 if (!ins[v]) 38 { 39 ins[v]=1; 40 q.push(v); 41 } 42 } 43 } 44 ins[u]=0; 45 } 46 } 47 int main() 48 { 49 while(~scanf("%d",&n)) 50 { 51 cnt=0; 52 memset(head,-1,sizeof(head)); 53 S=50001; 54 for (int i=1,x,y,z;i<=n;i++) 55 { 56 scanf("%d%d%d",&x,&y,&z); 57 if (x-1==-1) x=S+1; 58 add(x-1,y,z); 59 } 60 add(S,0,0);T=50000; 61 for (int i=1;i<=50000;i++) 62 add(i-1,i,0); 63 add(0,S,-1); 64 for (int i=1;i<=50000;i++) 65 add(i,i-1,-1); 66 Spfa(); 67 printf("%d\n",dis[T]); 68 } 69 }

POJ1201Intervals(差分約束系統)