[HNOI2009]最小圈,洛谷P3199,分數規劃+判負環
阿新 • • 發佈:2018-11-09
正題
要你求一個環,使得邊權除以點數最小。
就是求。
分數規劃,二分k,令這個東西小於k
得到
判定問題成為一個判斷圖中是否有負環,新邊的邊權是原來的邊權減去k。
判負環無高效演算法,dfs即可。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; int n,m; struct edge{ int x,y; double c; }p[10010]; struct new_edge{ int y,next; double c; }s[10010]; int first[3010],len=0; bool vis[3010],flag,tf[3010]; double dis[3010]; void ins(int x,int y,double c){ len++; s[len]=(new_edge){y,first[x],c};first[x]=len; } void dfs(int x){ for(int i=first[x];i!=0;i=s[i].next){ int y=s[i].y; if(dis[y]>dis[x]+s[i].c){ if(tf[y]){ flag=true; return ; } else{ dis[y]=dis[x]+s[i].c; tf[x]=true; dfs(y); tf[x]=false; if(flag) return ; } } } } bool check(double x){ len=0; memset(first,0,sizeof(first)); for(int i=1;i<=m;i++) ins(p[i].x,p[i].y,p[i].c-x); memset(dis,63,sizeof(dis)); memset(vis,false,sizeof(vis));flag=false; memset(tf,false,sizeof(tf)); for(int i=1;i<=n;i++) if(!vis[i] && !flag) dis[i]=0,dfs(i); return flag; } int main(){ scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) scanf("%d %d %lf",&p[i].x,&p[i].y,&p[i].c); double l=-1e7,r=1e7; while(r-l>=1e-9){ double mid=(l+r)/2; if(check(mid)) r=mid; else l=mid; } printf("%.8lf",l); }