您的位置:首页 > 编程语言 > Go语言

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

2015-08-22 01:29 786 查看
原题链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2031

题意

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

题解

一种做法是强行把所有环搞出来,然后检查即可。不过这种做法好难写。。。。

我的做法是二分答案:若当前的二分值是mid,让所有的边都减去这个值,如果此时图中出现负环,则说明有环的平均值比这个更小(为什么请脑补)。

代码

#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<cstdio>
#define MAX_N 66
#define INF 50000000000
#define eps 1e-4
using namespace std;

typedef long long ll;

int T;
int n,m;

struct edge {
public:
int to;
double cost;

edge(int t, double c) : cost(c), to(t) { }

edge() { }
};

vector<edge> G[MAX_N];
int cas = 0;

queue<int> que;
bool inQue[MAX_N];
double d[MAX_N];
int cnt[MAX_N];

bool vis[MAX_N];

bool spfa(int s) {
fill(d, d + n + 1, INF);
while (que.size())que.pop();
memset(inQue, 0, sizeof(inQue));
que.push(s);
inQue[s] = 1;
d[s] = 0;
memset(cnt, 0, sizeof(cnt));
cnt[s]++;
while (que.size()) {
int u = que.front();
vis[u]=1;
que.pop();
inQue[u] = 0;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i].to;
double t = G[u][i].cost + d[u];
if (t < d[v]) {
d[v]=t;
if(!inQue[v]) {
que.push(v);
inQue[v] = 1;
cnt[v]++;
if (cnt[v] > n)return true;
}
}
}
}
return false;
}

bool check(double mid) {
for (int i = 1; i <= n; i++)
for (int j = 0; j < G[i].size(); j++)
G[i][j].cost -= mid;
bool flag;
memset(vis, 0, sizeof(vis));
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 < G[i].size(); j++)
G[i][j].cost += mid;
return flag;
}

int main() {
cin.sync_with_stdio(false);
cin >> T;
while (T--) {
cin >> n >> m;
for (int i = 0; i <= n; i++)G[i].clear();
int u, v;
double c;
for (int i = 0; i < m; i++) {
cin >> u >> v >> c;
G[u].push_back(edge(v, c));
}

double l = 0, r = 10000005;
while (l + eps < r) {
double mid = (l + r) / 2;
if (check(mid))r = mid;
else l = mid;
}
if (!(fabs(r-10000005)<eps))
cout << "Case #" << ++cas << ": " << setprecision(2) << fixed << l << endl;
else
cout << "Case #" << ++cas << ": No cycle found." << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: