luogu P3199 [HNOI2009]最小圈

在这里插入图片描述

analysis

首先要理解题目中的那个"圈"的含义

这个圈不是强连通分量!这就说明这个题和scc或tarjan没什么关系

因为他说的是: c = ( c 1 , c 2 , ⋯ &ThinSpace; , c k ) ( c i ∈ V ) c=(c_1,c_2,\cdots,c_k)(c_i\in V) c=(c1,c2,,ck)(ciV) G G G中的一个圈当且仅当 ( c i , c i + 1 ) ( 1 ≤ i &lt; k ) (c_i,c_{i+1})(1\le i&lt;k) (ci,ci+1)(1i<k) ( c k , c 1 ) (c_k,c_1) (ck,c1)都在 E E E中,也就是说,只要在E中…

等等,这个E是边集的意思啊,也就是说如果 c i c_i ci c j c_j cj要在一个圈里面,必须顺次连接,那不就是环嘛!!,一开始还分析错了

然后就是这个答案,要求的是 μ ′ ( c ) = M i n ( μ ( c ) ) \mu&#x27;(c)=Min(\mu(c)) μ(c)=Min(μ(c)),也就是最小的 ∑ i = 1 k w c i , c i + 1 k \frac{\sum\limits_{i=1}^{k}w_{c_i,c_{i+1}}}{k} ki=1kwci,ci+1

诶想到一个变形,上面这个式子可以变成这样子: ∑ i = 1 k w c i , c i + 1 ∑ i = 1 k z i ( z i = 1 ) \frac{\sum\limits_{i=1}^{k}w_{c_i,c_{i+1}}}{\sum\limits_{i=1}^{k}z_i}(z_i=1) i=1kzii=1kwci,ci+1(zi=1)

即: ∑ i = 1 k x i × w c i , c i + 1 ∑ i = 1 k x i × z i ( z i = 1 ) \frac{\sum\limits_{i=1}^{k}x_i\times w_{c_i,c_{i+1}}}{\sum\limits_{i=1}^{k}x_i\times z_i}(z_i=1) i=1kxi×zii=1kxi×wci,ci+1(zi=1)

这个式子好生熟悉,不就是01分数规划哇
f ( x i ) = ∑ i = 1 k x i × w c i , c i + 1 ∑ i = 1 k x i × z i ( z i = 1 ) f(x_i)=\frac{\sum\limits_{i=1}^{k}x_i\times w_{c_i,c_{i+1}}}{\sum\limits_{i=1}^{k}x_i\times z_i}(z_i=1) f(xi)=i=1kxi×zii=1kxi×wci,ci+1(zi=1)
假设有一个组解满足 f ( x i ) &lt; L f(x_i)&lt;L f(xi)<L

∑ i = 1 k x i × w c i , c i + 1 ∑ i = 1 k x i × z i &lt; L \frac{\sum\limits_{i=1}^{k}x_i\times w_{c_i,c_{i+1}}}{\sum\limits_{i=1}^{k}x_i\times z_i}&lt;L i=1kxi×zii=1kxi×wci,ci+1<L

∑ i = 1 k x i × w c i , c i + 1 &lt; ∑ i = 1 k L × x i × z i {\sum\limits_{i=1}^{k}x_i\times w_{c_i,c_{i+1}}}&lt;{\sum\limits_{i=1}^{k}L\times x_i\times z_i} i=1kxi×wci,ci+1<i=1kL×xi×zi

∑ i = 1 k ( x i × w c i , c i + 1 − L × x i × z i ) &lt; 0 {\sum\limits_{i=1}^{k}(x_i\times w_{c_i,c_{i+1}}-L\times x_i\times z_i)}&lt;0 i=1k(xi×wci,ci+1L×xi×zi)<0

如果存在一组解使得图中存在负环,那么当前的二分值就不是最小的

这下就是判负环了对吧

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define ll long long
template<typename T>void read(T &x){
	x=0;char r=getchar();T neg=1;
	while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
	while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
	x*=neg;
}
const int maxn=3000+10;
const int maxm=10000+10;
int n,m,cnt=0;
struct node{
	int e;
	double w;
	int nxt;
}edge[maxm];
int head[maxn];
inline void addl(int u,int v,double w){
	edge[cnt].e=v;
	edge[cnt].w=w;
	edge[cnt].nxt=head[u];
	head[u]=cnt++;
}
bool flag=false;
bool insta[maxn];
bool vis[maxn];
double dis[maxn];
void spfa(int u,double L){
	insta[u]=true;
	for(int i=head[u];i!=-1;i=edge[i].nxt){
		int v=edge[i].e;
		if(dis[v]>dis[u]+edge[i].w-L){
			dis[v]=dis[u]+edge[i].w-L;
			if(insta[v]||flag){
				flag=true;
				return;
			}
			vis[v]=true;
			spfa(v,L);
		}
	}
	insta[u]=false;
}
void bin(){
	double L=-1e7,R=1e7,eps=1e-10;
	while(R-L>eps){
		double mid=(L+R)/2;
		//loop(i,1,n)dis[i]=1e9;
		clean(dis,0);
		clean(vis,false);
		clean(insta,false);
		loop(i,1,n){
			if(!vis[i]){
				vis[i]=1;
				flag=false;
				spfa(i,mid);
				if(flag){
					R=mid;
					break;
				}
			}
		}
		if(!flag)L=mid;
	}
	printf("%.8lf\n",L);
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("datain.txt","r",stdin);
	#endif
	clean(head,-1);
	read(n);read(m);
	loop(i,1,m){
		int ai,bi;
		double wi;
		read(ai);
		read(bi);
		scanf("%lf",&wi);
		addl(ai,bi,wi);
	}
	bin();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndrewMe8211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值