bzoj 1731 poj:3169 Layout (luogu 4878)
阿新 • • 發佈:2018-12-11
luogu有hack資料,70分,調不過
演算法:差分約束
難度:NOIP
* 親測,hack資料包括自正環,自負環,正環,負環,無環,假環...*
題目簡述:給你n頭奶牛,其中一些兩個距離不能超過D,而有些必須大於等於D,問1到n的最大距離。
明顯的差分約束,要求最大值,所以跑最短路,將一切不等式轉化為"<="的形式,
注意要判環,因為是負環,所以用spfa(SLF優化)跑最短路即可。
不清楚luogu hack 資料怎麼辦... 逃...
放棄
程式碼如下:
#include <cstdio> #include <iostream> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <deque> #include <queue> #define ll long long #define N 20005 using namespace std; struct node { int next; int to; int val; }edge[N<<1]; int head[N],vis[N],dis[N]; int cnt=1; void init() { memset(head,-1,sizeof(head)); cnt=1; } void add(int u,int v,int w) { edge[cnt].next=head[u]; edge[cnt].to=v; edge[cnt].val=w; head[u]=cnt++; } int cir[N],n,ml,md;; void spfa(int rt) { memset(dis,0x3f3f3f3f,sizeof(dis)); deque<int>Q; Q.push_front(rt); vis[rt]=1; dis[rt]=0; cir[rt]=1; while(!Q.empty()) { int u=Q.front(); Q.pop_front(); for(int i = head[u];i != -1;i = edge[i].next) { int to=edge[i].to; if(dis[to]>dis[u]+edge[i].val) { dis[to]=dis[u]+edge[i].val; if(++cir[to]>n) { puts("-1"); exit(0); } if(!vis[to]) { if(!Q.empty()&&dis[to]<dis[Q.front()]) { Q.push_front(to); }else { Q.push_back(to); } } } } vis[u]=0; } if(dis[n]==0x3f3f3f3f) { puts("-2"); exit(0); } } int main() { scanf("%d%d%d",&n,&ml,&md); init(); for(int i = 1;i <= ml;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); } for(int i = 1;i <= md;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(v,u,-w); } spfa(1); printf("%d\n",dis[n]); return 0 ; }