UVA 11090 Going in Cycle!! SPFA判断负环+二分

    xiaoxiao2021-03-25  157

    题目链接:

    https://vjudge.net/problem/UVA-11090

    题意:

    给你一个有向图,问你定义一个环的平均值为这个环上所有边的平均值,问你最小的环的平均值是多少

    题解:

    二分答案:若当前的二分值是mid,让所有的边都减去这个值,如果此时图中出现负环,则说明有环的平均值比这个更小

    假设一个包含k条边的回路,回路上各条边的权值为w1,w2……wk,那么平均值小于mid意味着 w1+w2+……wk< k* mid即: (w1-mid)+(w2-mid)+……(wk-mid)<0 有负环,当前平均值就大了

    注意图可能不连通,每个没访问过得点都spfa判一遍

    代码:

    #include <bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } // const int maxn = 50+10; double eps = 1e-6; int n,m; vector<pair<int,double> > G[maxn]; int vis[maxn],inq[maxn],cnt[maxn]; double d[maxn]; bool spfa(int u){ MS(inq);MS(cnt); for(int i=0; i<=n; i++) d[i] = INF; queue<int> q; q.push(u),inq[u]=1,d[u]=0; while(!q.empty()){ int now = q.front(); q.pop(); inq[now] = 0; vis[now] = 1; for(int i=0; i<(int)G[now].size(); i++){ int v = G[now][i].first; double w = G[now][i].second; if(d[v] > d[now]+w){ d[v] = d[now]+w; if(inq[v]) continue; inq[v] = 1; q.push(v); cnt[v]++; if(cnt[v] > n) return true; } } } return false; } bool check(double x){ for(int i=1; i<=n; i++) for(int j=0; j<(int)G[i].size(); j++) G[i][j].second -= x; // 让所有的边都减去mid,如果此时图中出现负环,则说明有环的平均值比这个更小 MS(vis); bool flag; for(int i=1; i<=n; i++){ if(!vis[i]) // 图可能不连通,每个没访问过得点都判一遍 flag = spfa(i); if(flag) break; } for(int i=1; i<=n; i++) for(int j=0; j<(int)G[i].size(); j++) G[i][j].second += x; return flag; // flag为true 就是有负环,当前平均值就大了 } int main(){ int T = read(); for(int cas=1; cas<=T; cas++){ for (int i = 0; i <= n; i++)G[i].clear(); scanf("%d%d",&n,&m); for(int i=1; i<=m; i++){ int u,v; double w; scanf("%d%d%lf",&u,&v,&w); G[u].push_back(MP(v,w)); } double L=0,R=1e7,ans=1e7; while((R-L)>eps){ double mid = (L+R)/2; if(check(mid)) ans=mid,R=mid-eps; else L=mid+eps; } if(abs(ans-1e7)<eps) printf("Case #%d: No cycle found.\n",cas); else printf("Case #%d: %.2lf\n",cas,ans); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-6539.html

    最新回复(0)