传送门
题意:在带权有向图中,求图中所有环的平均值的最小值(环的平均值即构成环的所有边的边权的平均值).
分析:理解题意,我们要求的实际上就是\(\frac{\sum_{i=1}^k{c_i}}{k}\)
令\(x=\frac{\sum_{i=1}^k{c_i}}{k}\)
整理得\(\sum_{i=1}^k{c_i}-k*x=0\)
继续得\(\sum_{i=1}^k(c_i-x)=0\)
令\(f(x)=\sum_{i=1}^k(c_i-x)\)
f(x)随x增大而减小,即f(x)是一个递减函数,既然具有单调性,就要想到二分答案.
我们直接二分要求的答案x,check时把每条边的边权看作\(c_i-x\),如果此次二分的值合法,即\(\frac{\sum_{i=1}^k{c_i}}{k}<x\),根据上面的推导得\(\sum_{i=1}^k(c_i-x)<0\),即图中存在一个负环.
所以本题就转换为了二分x,把每条边权看作\(c_i-x\),然后判断图中是否存在负环.
我写的是dfs+spfa判负环(如果不会判负环,请看广告).
注意本题是实数域上的二分答案.
int n,m,visit[3005];
int tot,head[3005],nxt[10005],to[10005];
double eps=1e-10;
double w[10005],dis[3005];
void add(int a,int b,double c){
nxt[++tot]=head[a];
head[a]=tot;
to[tot]=b;
w[tot]=c;
}
bool dfs_spfa(int x,double mid){
visit[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(dis[y]>dis[x]+w[i]-mid){
dis[y]=dis[x]+w[i]-mid;
if(visit[y]||dfs_spfa(y,mid))
return 1;
}
}
visit[x]=0;
return 0;
}
bool check(double mid){
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++)dis[i]=0;
for(int i=1;i<=n;i++)
if(dfs_spfa(i,mid))return 1;
return 0;
}
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);
}
double l=-1e9,r=1e9,mid;
while(l+eps<r){
mid=(l+r)/2.0;
if(check(mid))r=mid;
else l=mid;
}
printf("%.8lf\n",r);
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 2025成都.NET开发者Connect圆满结束
· 后端思维之高并发处理方案
· 千万级大表的优化技巧
· 在 VS Code 中,一键安装 MCP Server!
· 10年+ .NET Coder 心语 ── 继承的思维:从思维模式到架构设计的深度解析