题解:UVA11090 Going in Cycle!!
wjyppm1403 · · 题解
可能更好的阅读体验
本题就是大名鼎鼎的最优比率环的问题。
我们不难注意到,平均值就是如下:
其中
学过分数规划的想必已经秒了,没事我们一步一步推。
根据题意有:
这是什么,负环?我们把边权改成
根据上面的不等式,我们不难看出我们需要二分这个
接下来是代码时间,但是这里需要有几点注意:
- BFS 的 SPFA 会炸,请使用 DFS 版本的 SPFA,详情见代码。
- double 精度不够,请使用 long double。
- 时刻注意精度问题!
- 最后结果要输出
\dfrac{l+r}{2} ,不然会被 hack 精度(没错 long double 还是不够)。
代码通过 uDebug 上所有 hack,同时讨论区内个人 hack 也通过,感谢 hack 提供者们的贡献。也欢迎来 hack 我代码 www。
#include<bits/stdc++.h>
#define double long double
using namespace std;
constexpr int MN=55;
constexpr double eps=1e-10;
struct Edge{
int v;
double w;
};
int n,m,tot;
double l,r,dis[MN];
bool vis[MN];
vector<Edge> adj[MN];
int cmp(double x,double y){
if(fabs(x-y)<eps) return 0;
if(x>y) return 1;
return -1;
}
bool dfs(int u,double k){
vis[u]=1;
for(auto e:adj[u]){
int v=e.v;
auto w=e.w;
if(dis[v]>dis[u]+w-k){
dis[v]=dis[u]+w-k;
if(vis[v]||dfs(v,k)){
return vis[u]=0,1;
}
}
}
return vis[u]=0;
}
bool check(double k){
memset(dis,0,sizeof(dis));
for(int i=1;i<=n;i++){
if(dfs(i,k)) return 1;
}
return 0;
}
void init(){
for(int i=1;i<=n;i++) adj[i].clear(),vis[i]=0;
}
void solve(){
init();
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
double w;
cin>>u>>v>>w;
adj[u].push_back({v,w});
}
l=0,r=1e9;
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
if(cmp(l,1e9)==0) cout<<"No cycle found.\n";
else cout<<fixed<<setprecision(2)<<(l+r)/2<<'\n';
}
int main(){
int T;
cin>>T;
while(T--){
cout<<"Case #"<<++tot<<": ";
solve();
}
return 0;
}