【补题日记】[2022牛客暑期多校2]D-Link with Game Glitch

该博客主要探讨图论中的一个重要问题,即如何在加权图中找到使得所有边权之积大于1的最小权重w。通过二分查找和SPFA算法,判断是否存在负环,从而确定w的最大值。文章深入浅出地解释了如何利用图的性质进行算法设计,并提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pro

https://ac.nowcoder.com/acm/problem/239341

Sol

建图就是从b到d连一条 c a \frac{c}{a} ac的边,所以问题可以转化为,当图中每条边的权值都乘w后,图中都会存在一个环,其边权之积大于1,求不满足此条件的w最大值。

答案存在单调性,即w越大时边权之积越大,反之成立。那么考虑二分w,此处边权之积可能很大,所以对其取log,则转化为与0之间的比较,即判断正负环的问题,可以直接套用spfa求负环的模板。

Code

//By cls1277
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Eo(i,x,_) for(LL i=head[x]; i; i=_[i].next)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define endl '\n'

const LL maxn = 1005;
const LL maxm = 2005;
const double eps = 1e-10;
LL n, m, head[maxn], tot, cnt[maxn];
double dis[maxn];
bool vis[maxn];

struct Edge {
    LL to, next; double len;
}e[maxm];

void add(LL x, LL y, double z) {
    tot++;
    e[tot].next = head[x];
    e[tot].to = y;
    e[tot].len = z;
    head[x] = tot;
}

bool judge(double w) {
	queue<LL>q;
    for(int i=1; i<=n; i++) {
        dis[i] = 0;
        cnt[i] = vis[i] = 0;
        q.push(i);
    }
	while(!q.empty()) {
		LL u = q.front();
		q.pop();
		vis[u] = 0;
		for(int i=head[u]; i; i=e[i].next) {
			LL v = e[i].to;
			if(dis[v]>dis[u]+e[i].len+w) {
				dis[v] = dis[u]+e[i].len+w;
				if(!vis[v]) {
					vis[v] = 1;
					q.push(v);
                    cnt[v] = cnt[u]+1;
                    if(cnt[v]>=n) return 1;
				}
			} 
		} 
	}
    return 0;
}

int main() {
//    ios::sync_with_stdio(false);
//    cin.tie(nullptr);
    #ifdef DEBUG
    freopen("data.txt","r",stdin);
    #endif
    cin>>n>>m;
    Fo(i,1,m) {
        LL a, b, c, d; cin>>a>>b>>c>>d;
        add(b, d, -log(c*1.0/a));
    }
    double l=0, r=1;
    while(r-l>eps) {
        double mid = (l+r)/2;
        if(judge(-log(mid))) r = mid;
        else l = mid;
    }
//    cout<<l;
	printf("%.10lf",l);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cls1277

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

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

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

打赏作者

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

抵扣说明:

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

余额充值