题目大意:给出一个有向图,求这个图的路径长度平均值最小的环。
思路:二分这个答案,然后将所有边权都减去这个二分的值,对于所有节点进行DFS,这个过程中只沿着长度不断减少的方向搜,如果搜回了自己,说明可以降低界,否则提升下界。
不要用SPFA判负环,因为会T。
CODE:
#include <cmath> #include <cstdio> #include <iomanip> #include <cstring> #include <iostream> #include <algorithm> #define MAX 3010 #define MAXE 10010 #define INF 1e10 #define EPS 1e-12 using namespace std; int points,edges; double len; int head[MAX],total; int next[MAXE],aim[MAXE]; double length[MAXE]; inline void Add(int x,int y,double len) { next[++total] = head[x]; aim[total] = y; length[total] = len; head[x] = total; } bool v[MAX]; double mid,f[MAX]; void DFS(int x) { if(v[x]) throw true; v[x] = true; for(int i = head[x]; i; i = next[i]) if(f[x] + length[i] - mid < f[aim[i]]) { f[aim[i]] = f[x] + length[i] - mid; DFS(aim[i]); } v[x] = false; } double l = -INF,r = INF; int main() { cin >> points >> edges; for(int x,y,i = 1; i <= edges; ++i) { scanf("%d%d%lf",&x,&y,&len); Add(x,y,len); l = min(l,len); r = max(r,len); } while(fabs(r - l) > EPS) { mid = (l + r) / 2.0; bool flag = false; for(int i = 1; i <= points; ++i) { try { memset(f,0,sizeof(f)); memset(v,false,sizeof(v)); DFS(i); }catch(bool) { flag = true; break; } } if(flag) r = mid; else l = mid; } if(fabs(l) < EPS) cout << "0.00000000" << endl; else cout << fixed << setprecision(8) << l << endl; return 0; }
原文地址:http://blog.csdn.net/jiangyuze831/article/details/42678035