BZOJ 1486 HNOI 2009 最小圈 DFS

来源:互联网 发布:平板电脑 收银软件 编辑:程序博客网 时间:2024/06/05 00:52

题目大意:给出一个有向图,求这个图的路径长度平均值最小的环。


思路:二分这个答案,然后将所有边权都减去这个二分的值,对于所有节点进行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-12using 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;}


0 0
原创粉丝点击