analysis
首先要理解题目中的那个"圈"的含义
这个圈不是强连通分量!这就说明这个题和scc或tarjan没什么关系
因为他说的是: c = ( c 1 , c 2 , ⋯   , c k ) ( c i ∈ V ) c=(c_1,c_2,\cdots,c_k)(c_i\in V) c=(c1,c2,⋯,ck)(ci∈V)是 G G G中的一个圈当且仅当 ( c i , c i + 1 ) ( 1 ≤ i < k ) (c_i,c_{i+1})(1\le i<k) (ci,ci+1)(1≤i<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'(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=1∑kwci,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=1∑kzii=1∑kwci,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=1∑kxi×zii=1∑kxi×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=1∑kxi×zii=1∑kxi×wci,ci+1(zi=1)
假设有一个组解满足
f
(
x
i
)
<
L
f(x_i)<L
f(xi)<L
则 ∑ i = 1 k x i × w c i , c i + 1 ∑ i = 1 k x i × z i < 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}<L i=1∑kxi×zii=1∑kxi×wci,ci+1<L
∑ i = 1 k x i × w c i , c i + 1 < ∑ i = 1 k L × x i × z i {\sum\limits_{i=1}^{k}x_i\times w_{c_i,c_{i+1}}}<{\sum\limits_{i=1}^{k}L\times x_i\times z_i} i=1∑kxi×wci,ci+1<i=1∑kL×xi×zi
∑ i = 1 k ( x i × w c i , c i + 1 − L × x i × z i ) < 0 {\sum\limits_{i=1}^{k}(x_i\times w_{c_i,c_{i+1}}-L\times x_i\times z_i)}<0 i=1∑k(xi×wci,ci+1−L×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;
}