题意:给出一张边权为正整数的有向图,求一个平均权值最小的回路的平均权值。
思路:二分这个最小的平均权值p,再将所有的边权减去p,用spfa判负环。如果此时图中有负环,则说明存在比p更小的平均权值。
注意:这题本机过了提交却WA,看了很久才发现输出double时吧%lf写成了%llf……qwq
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 50
#define db double
struct Pair {
int x;
db y;
Pair(int xx=0,db yy=0) {
x=xx,y=yy;
}
};
int n,m;
vector<Pair> a[maxn+5];
bool spfa() {
queue<int> que;
int cnt[maxn+5]= {0};
db dist[maxn+5]= {0};
bool u[maxn+5]= {0};
for(int i=1; i<=n; i++) {
que.push(i);
dist[i]=0,u[i]=true;
}
while(!que.empty()) {
int h=que.front();
que.pop();
u[h]=false;
for(int i=0; i<a[h].size(); i++) {
int x=a[h][i].x;
db y=a[h][i].y;
if(dist[x]>dist[h]+y) {
dist[x]=dist[h]+y;
if(!u[x]) {
u[x]=true,que.push(x);
if(++cnt[x]>n) return false;
}
}
}
}
return true;
}
bool judge(db x) {
for(int i=1; i<=n; i++) {
for(int j=0; j<a[i].size(); j++) {
a[i][j].y-=x;
}
}
bool ans=spfa();
for(int i=1; i<=n; i++) {
for(int j=0; j<a[i].size(); j++) {
a[i][j].y+=x;
}
}
return ans;
}
db binsearch(db rr) {
db l=0,r=rr;
while(l+(1e-4)<r) {
db mid=l+(r-l)/2;
if(judge(mid)) l=mid;
else r=mid;
}
return l;
}
void init() {
for(int i=0; i<=maxn; i++) a[i].clear();
}
db readin() {
db r=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++) {
int x,y;
db z;
scanf("%d%d%lf",&x,&y,&z);
a[x].push_back(Pair(y,z));
r=max(r,z);
}
return r;
}
int main() {
int T;
scanf("%d",&T);
for(int t=1; t<=T; t++) {
init();
db r=readin();
if(judge(r+1)) printf("Case #%d: No cycle found.\n",t);
else {
db ans=binsearch(r);
printf("Case #%d: %.2lf\n",t,ans);
}
}
return 0;
}