P4878 [USACO05DEC]Layout G 差分約束
阿新 • • 發佈:2020-07-16
題目大意
- 和人類一樣,奶牛們在打飯的時候喜歡和朋友站得很近。
- 約翰的編號為 1 到 n 的 n(2<=n<=1000) 只奶牛正打算排隊打飯。現在請你來安排她們,讓她們在數軸上排好隊。奶牛的彈性很好,同一個座標可以站無限只奶牛,排隊的順序必須和她們編號的順序一致。
- 有 M 對奶牛互相愛慕,她們之間的距離不能超過一定的值,有 K 對奶牛互相敵視,她們的距離不能小於一定的值。那麼,首尾奶牛的最大距離是多少呢?
輸入格式
- 第一行輸入 n,M,K,(0<M,K<=5000)。
- 接下來 M 行每行三個整數x,y,z,表示編號為 x 和 y 的兩頭奶牛之間的距離最大不超過 z。
- 再接下來 K 行每行三個整數 a,b,c,表示編號為 a 和 b 的兩頭奶牛之間的距離最少為c。
輸出格式
- 如果沒有合理方案,輸出 −1,如果首尾兩頭牛的距離可以無限大,輸出 −2,否則輸出一個整數表示首尾奶牛的最大距離。
樣例輸入
4 2 1
1 3 10
2 4 20
2 3 3
樣例輸出
27
演算法分析
- 不會吧不會吧不會真的有人看不出來這是差分約束吧
- 然後就是一個差分約束的板子題了
- 建邊跑最短路(求最大值)
- 建超級源點
演算法展示
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3+10,maxm = 2e4+10; const int Inf = 0x3f3f3f3f; int n; int head[maxn],cnt; int num[maxn],dis[maxn],vis[maxn]; struct node{ int next,to,dis; }a[maxm]; void add(int x,int y,int z){ a[++cnt].to = y; a[cnt].next = head[x]; a[cnt].dis = z; head[x] = cnt; } queue<int> q; int spfa(int u){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); q.push(u);vis[u] = 1; dis[u] = 0; while(!q.empty()){ int u = q.front();q.pop();vis[u] = 0; for(int i = head[u];i;i = a[i].next){ int v = a[i].to; if(dis[v] > dis[u] + a[i].dis){ dis[v] = dis[u] + a[i].dis; if(!vis[v]){ vis[v] = 1;q.push(v); num[v]++; if(num[v] > n)return -1;//判負環 } } } } if(dis[n] == Inf)return -2;//如果無限大 return dis[n]; } int main(){ int m,k;scanf("%d%d%d",&n,&m,&k); for(int i = 1;i <= m;++i){ int x,y,z;scanf("%d%d%d",&x,&y,&z); if(x > y)swap(x,y); add(x,y,z); } for(int i = 1;i <= k;++i){ int x,y,z;scanf("%d%d%d",&x,&y,&z); if(x > y)swap(x,y); add(y,x,-z);//建邊 } for(int i = 1;i < n;++i)add(i+1,i,0);//建邊 for(int i = 1;i <= n;++i)add(0,i,0);//超級源點 if(spfa(0) == -1){printf("-1\n");return 0;}//超級源點為起點跑spfa 防止有的負環無法到達的情況 printf("%d\n",spfa(1)); return 0; }
謝謝觀看>:<