洛谷 P3199 [HNOI2009]最小圈
题目背景
如果你能提供题面或者题意简述,请直接在讨论区发帖,感谢你的贡献。
题目描述
对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值
输入输出格式
输入格式:
第一行2个正整数,分别为n和m
以下m行,每行3个数,表示边连接的信息,
输出格式:
一行一个数,表示最小圈的值,保留8位小数。
输入输出样例
输入样例#1:
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
输出样例#1:
3.66666667
说明
若设边权为vv,那么n\le 3000,m\le 10000,v\le 50000n≤3000,m≤10000,v≤50000
思路:分数规划
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 10010 using namespace std; int n,m,tot; double l,r,mid,ans; int vis[MAXN]; double dis[MAXN],cap[MAXN]; int to[MAXN],net[MAXN],head[MAXN]; void add(int u,int v,double w){ to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot; } bool spfa(int now){ vis[now]=1; for(int i=head[now];i;i=net[i]) if(dis[to[i]]>dis[now]-mid+cap[i]){ dis[to[i]]=dis[now]-mid+cap[i]; if(vis[to[i]]||spfa(to[i])){ vis[to[i]]=0; return true; } } vis[now]=0; return false; } bool chack(){ memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); for(int i=1;i<=n;i++) if(spfa(i)) return false; return true; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int a,b; double c; scanf("%d%d%lf",&a,&b,&c); add(a,b,c); } l=0;r=100000; while(r-l>0.000000001){ mid=(l+r)/2; if(chack()){ ans=mid; l=mid; } else r=mid; } printf("%.8lf",ans); } /* 4 5 1 2 5 2 3 5 3 1 5 2 4 3 4 1 3 */
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。