uva11090【Going in Cycle】

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

【题解】

   最优比例环

  

用二分答案。假设答案为mid,只需要判断是否存在平均值小于mid的回路。

假设一个包含k条边的回路,回路上各条边的权值为w1,w2……wk,那么平均值小于mid意味着 w1+w2+……wk< k* mid即:

(w1-mid)+(w2-mid)+……(wk-mid)<0 (这个就是最优比例环的简化版点权为1)

换句话说,只要把图中每一条边a,b的权值w(a,b)变为w(a,b)-mid,在判断图中有没有负权回路。




#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
double a[1500],d[1500],l,r,mid,o;
struct info
  {
  	int ar,next;
  	double l;
  }road[10005];
int first[1500],i,j,k,m,num,n,sum,q[1500],c[1500],f[1500],p1,q1,vis[1500],T;
void add(int x,int y,double len)
  {
     num++;
	 road[num].ar=y;road[num].next=first[x];
	 road[num].l=len;first[x]=num;
  }
int spfa(double k,int z)
  {
  	int i,h,t,u,v;
  	memset(c,0,sizeof(c));
  	memset(f,0,sizeof(f));
  	for (i=1;i<=n;i++) d[i]=1e9;
  	t=1;h=0;q[1]=z;d[z]=0;f[z]=1;c[z]=1;
  	for (;h!=t;)
  	  {
		h++;if (h==1500) h=0;u=q[h];f[u]=0;vis[u]=1;
		for (i=first[u];i;i=road[i].next)
		  {
		  	v=road[i].ar;
		  	if (d[u]+road[i].l-a[v]*k<d[v]) 
		  	  {
		  	  	d[v]=d[u]+road[i].l-a[v]*k;
		  	  	if (!f[v])
		  	  	  {
		  	  	  	t++;if (t==1500) t=0;
		  	  	  	q[t]=v;f[v]=1;c[v]=c[u]+1;
		  	  	  	if (c[v]>n) return 1;
				  }
			  }
		  } 
	  }
	return 0;
  }
int pd(double k)
  {
  	int i;
  	 memset(vis,0,sizeof vis);
  	for (i=1;i<=n;i++)
  	  if (!vis[i]) 
  	    if (spfa(k,i)) return 1;
  	return 0;
  }
int main()
  {
  	for (sum=0,scanf("%d",&T);T;T--)
  	{
  	 
  	  sum++;num=0;memset(first,0,sizeof first);
  	  memset(vis,0,sizeof vis);
  	  scanf("%d%d",&n,&m);r=0;l=0;
  	  for (i=1;i<=n;i++) a[i]=1;
      for (i=1;i<=m;i++)
  	    {
  	  	  scanf("%d%d%lf",&p1,&q1,&o);
  	  	  add(p1,q1,o);
	    }
	  r=1e12;
	  for (;r-l>1e-5;)
	    {
	  	  mid=(l+r)/2;
	  	  if (pd(mid)) r=mid;else l=mid; 
	    } 
	  printf("Case #%d: ",sum);
	  if (r==1e12) printf("No cycle found.\n");else printf("%.2f\n",r);
    }
  }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值