题意:给定一个n个点m条边的加权有向图,求平均权值最小的回路。
分析:二分+负权回路的判断,数据居然有自环,MDZZ,WA了一晚上。
#include <cstdio>
#include <stack>
#include <queue>
#include <vector>
#include <cstdio>
#include <utility>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
int T,n,m,num;
long long tot;
typedef pair <int,double> Pii;
bool jud[105];
double dis[105];
vector <Pii> G[105];
bool dfs(int u,double k)
{
jud[u] = true;
for(Pii x : G[u])
{
int v = x.first;
double val = x.second;
if(dis[u] + val - k < dis[v])
{
dis[v] = dis[u] + val - k;
if(jud[v]) return true;
if(dfs(v,k)) return true;
}
}
jud[u] = false;
return false;
}
bool Jud(double k)
{
for(int i = 1;i <= n;i++) dis[i] = 0;
memset(jud,0,sizeof(jud));
for(int i = 1;i <= n;i++)
if(dfs(i,k)) return true;
return false;
}
int main()
{
scanf("%d",&T);
while(T--)
{
tot = 0;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) G[i].clear();
while(m--)
{
int u,v,val;
scanf("%d%d%d",&u,&v,&val);
G[u].push_back(make_pair(v,val));
tot += val;
}
double l = 0,r = tot + 1;
while(r - l > eps)
{
double mid = (l+r)/2.0;
if(Jud(mid)) r = mid;
else l = mid;
}
printf("Case #%d: ",++num);
if(!Jud(r)) printf("No cycle found.\n");
else printf("%.2lf\n",l);
}
}