#include<bits/stdc++.h> #define debu using namespace std; const int maxn=100; struct Edge { int from,to; double dist; }; struct BellmanFord { int n,m; vector<Edge> edges; vector<int> G[maxn]; bool inq[maxn]; double d[maxn]; int p[maxn]; int cnt[maxn]; void init(int n) { this->n=n; for(int i=0; i<n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,double dist) { edges.push_back((Edge){from,to,dist}); m=edges.size(); G[from].push_back(m-1); } bool negativeCycle() { queue<int> q; memset(inq,0,sizeof(inq)); memset(cnt,0,sizeof(cnt)); for(int i=0; i<n; i++) { d[i]=0.0; inq[0]=true; q.push(i); } while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=false; for(int i=0; i<G[u].size(); i++) { Edge& e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=G[u][i]; if(!inq[e.to]) { q.push(e.to); inq[e.to]=true; if(++cnt[e.to]>n) return true; } } } } return false; } }; int n,m; double maxw; BellmanFord ans; int check(double val) { int flag=0; for(int i=0; i<m; i++) ans.edges[i].dist-=val; if(ans.negativeCycle()) flag=1; for(int i=0; i<m; i++) ans.edges[i].dist+=val; return flag; } double solve() { double mid; double l=0.0,r=maxw; if(!check(maxw+1)) return -1; while(r-l>1e-4) { mid=(l+r)/2; if(check(mid)) r=mid; else l=mid; //cout<<l<<" "<<r<<endl; } //cout<<l<<" "<<mid<<" "<<r<<endl; return l; } int main() { #ifdef debug freopen("in.in","r",stdin); #endif // debug int t,cas=0; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); maxw=0.0; ans.init(n); for(int i=0; i<m; i++) { int x,y; double w; scanf("%d%d%lf",&x,&y,&w); x--;y--; ans.AddEdge(x,y,w); maxw=max(maxw,w); } double ans=solve(); if(ans==-1) printf("Case #%d: No cycle found.\n",++cas); else printf("Case #%d: %.2f\n",++cas,ans); } return 0; }
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2031
题解:二分答案。原题可化为是否存在一个平均权值小于ave的回路,即w[1]+w[2]+......+w[k]<k*ave,也即(w[1]-ave)+(w[2]-ave)+.......+(w[k]-ave)<0。所以将各边权值每次减去ave,判断是否存在负环,若存在则该ave合法,继续二分求最小值。(注意当不存在环时,即使将每条边权值减去max{w}+1也不可能形成负环)。