题目大意:
就最小的环的平均权值
思路:
二分法枚举最小平均权值,如果有满足的环就return true
这里用到了dfs找还,每次都减去平均权值,如果距离是>0的证明列举的平均权值是可以的
当然这用到的vis是为了让循环停止
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 105;
const int INF = 0x3f3f3f3f;
int m, n;
struct node{
int v;
double w;
};
double d[maxn];
int vis[maxn];
vector<node> g[maxn];
void init() {
for(int i=1; i<=n; i++) g[i].clear();
memset(vis, 0, sizeof(vis));
}
bool dfs(int x, double k) {
vis[x] = 1;
for(int i=0; i<g[x].size(); i++) {
node& y = g[x][i];
if(d[y.v] > d[x]+y.w-k) {
d[y.v] = d[x]+y.w-k;
if(vis[y.v]) return true;
if(dfs(y.v, k)) return true;
}
}
vis[x] = false;
return false;
}
bool judge(double k) {
memset(vis, 0, sizeof(vis));
memset(d, 0, sizeof(d));
for(int i=1; i<=n; i++) {
if(dfs(i, k)) return true;
}
return false;
}
int main() {
int kase;
int num = 0;
scanf("%d", &kase);
int a, b;
double c;
while(kase--) {
double sum = 0;
double l, r;
scanf("%d%d", &n, &m);
init();
for(int i=0; i<m; i++) {
scanf("%d %d %lf", &a, &b, &c);
g[a].push_back((node){b, c});
sum += c;
}
l=0, r=sum+1;
while(r-l>1e-6) {
double mid = (r+l)/2.0;
if(judge(mid)) r=mid;
else l=mid;
}
printf("Case #%d: ",++num);
if(!judge(r)) printf("No cycle found.\n");
else printf("%.2lf\n",l);
}
return 0;
}