【差分约束系统/SPFA】POJ3169-Layout
【题目大意】
n头牛从小到大排,它们之间某些距离不能大于一个值,某些距离不能小于一个值,求第一头牛和第N头牛之间距离的最大值。
【思路】
由题意可以得到以下不等式d[AL]+DL≥d[BL];d[BD]+(-DD)≥d[AD];d[i+1]+0≥d[i],显然是差分约束系统。即构造从AL到BL权值为DL的边,从BD到AD构造权值为-DD的负边,从i+1到i构造权值为0的边。最后求最短路径。安利一个证明(点我)。
对于差分约束系统要注意的是,如果要求最大距离,用最短路径;求最小距离,用最长路径,要根据实际情况判断。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int MAXN=10000+5; 7 struct Rec 8 { 9 int ori,des,len; 10 }; 11 int n,ml,md; 12 int first[MAXN/10],next[MAXN*2+1000]; 13 Rec edge[MAXN*2+1000]; 14 int vis[MAXN/10],dis[MAXN/10],appear[MAXN/10]; 15 16 void init() 17 { 18 memset(first,-1,sizeof(first)); 19 scanf("%d%d%d",&n,&ml,&md); 20 int j=-1; 21 for (int i=0;i<ml;i++) 22 { 23 j++; 24 scanf("%d%d%d",&edge[j].ori,&edge[j].des,&edge[j].len); 25 edge[j].ori--;edge[j].des--; 26 next[j]=first[edge[j].ori]; 27 first[edge[j].ori]=j; 28 } 29 for (int i=0;i<md;i++) 30 { 31 j++; 32 scanf("%d%d%d",&edge[j].des,&edge[j].ori,&edge[j].len); 33 edge[j].ori--;edge[j].des--; 34 edge[j].len=0-edge[j].len; 35 next[j]=first[edge[j].ori]; 36 first[edge[j].ori]=j; 37 } 38 for (int i=1;i<n;i++) 39 { 40 j++; 41 edge[j].ori=i;edge[j].des=i-1;edge[j].len=0; 42 next[j]=first[edge[j].ori]; 43 first[edge[j].ori]=j; 44 } 45 } 46 47 void SPFA() 48 { 49 queue<int> que; 50 memset(vis,0,sizeof(vis)); 51 memset(appear,0,sizeof(appear)); 52 for (int i=1;i<n;i++) dis[i]=0x7fffffff; 53 dis[0]=0; 54 que.push(0); 55 vis[0]=1; 56 appear[0]++; 57 58 while (!que.empty()) 59 { 60 int head=que.front(); 61 int k=first[head]; 62 while (k!=-1) 63 { 64 Rec e=edge[k]; 65 if (dis[e.des]>dis[e.ori]+e.len) 66 { 67 dis[e.des]=dis[e.ori]+e.len; 68 if (!vis[e.des]) 69 { 70 appear[e.des]++; 71 if (appear[e.des]>n) 72 { 73 cout<<-1<<endl; 74 return; 75 } 76 que.push(e.des); 77 vis[e.des]=1; 78 } 79 } 80 k=next[k]; 81 } 82 vis[head]=0; 83 que.pop(); 84 } 85 if (dis[n-1]==0x7fffffff) cout<<-2<<endl; else cout<<dis[n-1]<<endl; 86 } 87 88 int main() 89 { 90 init(); 91 SPFA(); 92 system("pause"); 93 return 0; 94 }