您的位置:首页 > 其它

【UVA2031】cycle {二分+spfa/Bellman ford}

2016-10-30 00:12 316 查看
【题目描述】

给定一个有n个顶点m条边的加权有向图,如果图中存在环(回路),环的平均值等于,环上边的权值之和除以构成环的边数,图中可能不止存在一个回路,计算平均权值最小的回路。

【Sample Input】

(输入第一行为数据组数T(t<=10),每组数据第一行为图的点数n和边数m(n<=50).以下m行3个正整数u,v,w,表示有一条从u到v的有向边,权值为w,输入没有自环。)

2

2 1

1 2 1

2 2

1 2 2

2 1 3

【Sample Output】

(对于每组数据输出最小平均值,保留两位小数。如果无解,输出“No cycle found.” 每组数据输出格式如下(x表示第几组数据): Case #x:最小平均值或 No cycle found.)

Case #1: No cycle found.

Case #2: 2.50

【数据范围】

T<=10;n ≤ 50,m<=n*n;u, v ≤ n;w ≤ 10000000

【题解】二分+spfa或bellman ford判负环

本题要求最小平均环。直接搜索显然会超时(大概搜索拿了30)。在很难直接确定答案的情况下,考虑用二分来做。

二分之后我们有了可能的答案mid。考虑如果答案可行,即某个环的平均值小于等于此可能解,设这个环上的边劝为w[1]至w[k],则可以得到:

w[1]+w[2]+…+w[k]<=k*mid

→ (w[1]-mid)+(w[2]-mid)+…+(w[k]-mid)<=0

故而我们将所有边的权值减去mid,判断图内是否存在负环,若有则最小平均值<=当前答案。如果无论二分值多大都无法得到负环,则证明此图无环。

#include <cstdio>
#include <iostream>
#include <cstring>
#define N 55
#define inf 1000000000
int n,m,T,u[N*N],v[N*N],w[N*N];
double dis
,ans;
bool work(double x)
{
for (int i=1;i<=n;++i) dis[i]=0;
bool bo;
for (int i=1;i<=n;++i)
{
bo=false;
for (int j=1;j<=m;++j)
if (dis[v[j]]>dis[u[j]]+w[j]-x) dis[v[j]]=dis[u[j]]+w[j]-x,bo=true;
if (!bo) return false;
}
return true;
}
int main()
{
int cas=1;
for (scanf("%d\n",&T);T--;++cas)
{
printf("Case #%d: ",cas);
scanf("%d%d\n",&n,&m);
for (int i=1;i<=m;++i)
scanf("%d%d%d\n",&u[i],&v[i],&w[i]);
double l=0,r=1e8;
ans=-1.0;
for (;l+1e-6<r;)
{
double mid=0.5*(l+r);
if (work(mid)) r=mid,ans=mid;
else l=mid;
}
if (ans<0) printf("No cycle found.\n");
else printf("%.2f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva 二分答案