[SCOI2014]方伯伯運椰子,洛谷P3288,分數規劃+判斷負權環
阿新 • • 發佈:2018-11-09
正題
題目連結點這
如果我們給一條邊加1的流量,那麼費用是不是多了,給一條邊減1的流量,那麼費用多了。
這兩個都是挺明顯的吧。
考慮怎麼保證流量平衡。
設原邊為。
那麼建兩條邊,,現在改一個環就可以使得流量平衡。
為什麼?
假設這個環先走了一段一類邊,再走了一段二類邊,然後再走了一段一類邊。。。。。。
那麼在一類邊的交點和二類邊的交點的流量都是平衡的,二類邊相當於反向邊。畫圖看一下就明白了。
好,那麼這個環的邊權和就是。但是題目要我們求。
k為環的大小。
我們二分一個mid
然後令這個東西大於mid,看看發生什麼。
因為Y-X是環的邊權和,所以
令新邊權為,若能求出一個負環,那麼說明答案比mid大,否則答案小於等於mid。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; int n,m; struct new_edge{ int y,next; double c; }s[60010]; int first[5010],len=0; double dis[5010]; bool tf[5010]; void ins(int x,int y,double c){ len++; s[len]=(new_edge){y,first[x],c};first[x]=len; } bool dfs(int x,double temp){ tf[x]=true; for(int i=first[x];i!=0;i=s[i].next){ int y=s[i].y; if(dis[y]>dis[x]+s[i].c+temp){ if(tf[y]) return true; dis[y]=dis[x]+s[i].c+temp; if(dfs(y,temp)) return true; } } return tf[x]=false; } int main(){ scanf("%d %d",&n,&m); int x,y,a,b,c,d; for(int i=1;i<=m;i++){ scanf("%d %d %d %d %d %d",&x,&y,&a,&b,&c,&d); ins(x,y,b+d); if(c) ins(y,x,a-d); } double l=0,r=1e7; while(r-l>=1e-3){ for(int i=1;i<=n+2;i++) dis[i]=1e9,tf[i]=false; dis[n+1]=0; double mid=(l+r)/2; if(dfs(n+1,mid)) l=mid; else r=mid; } printf("%.2lf",l); }