BZOJ 1486 [HNOI2009] 最小圈

本文介绍了一种结合01分数规划与深度优先搜索(DFS)的方法来判断是否存在负环。通过二分查找确定使特定公式成立的k值,并使用类似于DFS的策略进行负环判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Input

Output

Sample Input

4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3

Sample Output

3.66666667

HINT

Source

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

01分数规划+dfs/SPFA判负环~

根据01分数规划,我们二分寻找能使sum{(a[i]-b[i]*k)*x[i]}==0的k值,然后判负环,如果有负环,就增大k值。

注意这道题卡SPFA判负环,只能用类似于dfs+SPFA的判断方法,详见代码~


#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define eps 1e-10

int n,m,x,y,fi[3001],w[20001],ne[20001],cnt;
bool b[3001];
double z,v[20001],ll[20001],mid,dis[3001];

void add(int u,int vv,double val)
{
	w[++cnt]=vv;ne[cnt]=fi[u];fi[u]=cnt;v[cnt]=val;
}

bool dfs(int u)
{
	b[u]=1;
	for(int i=fi[u];i;i=ne[i])
	  if(dis[w[i]]>ll[i]+dis[u])
	  {
		if(b[w[i]])
		{
			b[u]=0;return 1;
		}
		dis[w[i]]=ll[i]+dis[u];
		if(dfs(w[i]))
		{
			b[u]=0;return 1;
		}
	  }
	b[u]=0;
	return 0;
}

bool che()
{
	memset(dis,0,sizeof(dis));
	for(int i=1;i<=cnt;i++) ll[i]=v[i]-mid;
	for(int i=1;i<=n;i++) if(dfs(i)) return 1;
	return 0; 
}

int read()
{
	int totnum=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0' && ch<='9') {totnum=(totnum<<1)+(totnum<<3)+ch-'0';ch=getchar();}
	return totnum*f; 
}

int main()
{
	n=read();m=read();
	for(int i=1;i<=m;i++) x=read(),y=read(),scanf("%lf",&z),add(x,y,z);
	double l=-1e7,r=1e7;
	while(r-l>=eps)
	{
		mid=(l+r)*1.0/2.0;
		if(che()) r=mid;
		else l=mid; 
	}
	printf("%.8lf\n",mid);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值