其他分享
首页 > 其他分享> > #结论#洛谷 3199 [HNOI2009]最小圈

#结论#洛谷 3199 [HNOI2009]最小圈

作者:互联网

题目

求有向图最小平均权值回路。

\(n\leq 3*10^3,m\leq 10^4\)


分析

设 \(f_k(x)\) 表示从点 \(x\) 出发恰好走 \(k\) 条边的最短路,

那么答案就是 \(\min_{x=1}^n\max_{k=0}^{n-1}\frac{f_n(x)-f_k(x)}{n-k}\)

所以直接 \(O(nm)\) 就可以了,证明见_rqy dalao的博客

0/1分数规划的方法理论应该会T这里就不写了,不过只要任意点都可以作为起点那么初始值都为0就可以了


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=3411; typedef double db;
int as[N],n,m; db f[N][N],ans=1e15;
struct node{int y; db w; int next;}e[N*3];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline void Max(db &x,db y){x=x>y?x:y;}
inline void Min(db &x,db y){x=x<y?x:y;} 
signed main(){
    n=iut(); m=iut();
    for (rr int i=1;i<=m;++i){
        rr int x=iut(),y=iut();
        rr db w; scanf("%lf",&w);
        e[i]=(node){y,w,as[x]},as[x]=i;
    }
	for (rr int i=1;i<=n;++i){
		for (rr int x=1;x<=n;++x) f[i][x]=1e15;
		for (rr int x=1;x<=n;++x)
		if (f[i-1][x]!=1e15)
		   for (rr int j=as[x];j;j=e[j].next)
		       Min(f[i][e[j].y],f[i-1][x]+e[j].w);
	}
	for (rr int i=1;i<=n;++i){
		rr db now=-1e15;
	    for (rr int j=0;j<n;++j)
	        Max(now,(f[n][i]-f[j][i])/(n-j));
		Min(ans,now); 
	}
	return !printf("%.8lf",ans);
}

0/1分数规划代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=3011; int as[N],n,m; bool v[N]; double dis[N];
struct node{int y; double w; int next;}e[N*5];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline bool dfs(int x,double mid){
    v[x]=1;
    for (rr int i=as[x];i;i=e[i].next)
    if (dis[e[i].y]>dis[x]+e[i].w-mid){
        if (v[e[i].y]) return 0;
        dis[e[i].y]=dis[x]+e[i].w-mid;
        if (!dfs(e[i].y,mid)) return 0;
    }
    v[x]=0;
    return 1;
}
signed main(){
    n=iut(); m=iut();
    for (rr int i=1;i<=m;++i){
        rr int x=iut(),y=iut();
        rr double w; scanf("%lf",&w);
        e[i]=(node){y,w,as[x]},as[x]=i;
    }
    for (rr int i=1;i<=n;++i)
        e[i+m]=(node){i,0,as[n+1]},as[n+1]=m+i;
    rr double l=-5000,r=5000;
    while (l+1e-9<r){
        rr double mid=(l+r)/2;
        for (rr int i=1;i<=n+1;++i) dis[i]=v[i]=0;
        if (dfs(n+1,mid)) l=mid;
		    else r=mid;
    }
    return !printf("%.8lf",l);
}

标签:洛谷,rr,int,db,ans,isdigit,HNOI2009,include,3199
来源: https://www.cnblogs.com/Spare-No-Effort/p/15348539.html