"蔚来杯"2022牛客暑期多校训练营2 D Link with Game Glitch


https://ac.nowcoder.com/acm/contest/33187/D

建边 /((b,d,c/a)/),那么会无限就说明有一个环边积大于 0 的环。

化积为和,对于边权都取 /(/log_2/),那么二分 /(w/),将每条边的边权变为 /(e[i].w-w/),那么变为是否有一个环边和大于 0,考虑并不是很好做,于是对于所有边都取相反数,那么就是是否有一个环和小于 0,即负环。建虚点,连每个点跑 spfa,即可。刚刚复习了下才学到可以判经过的路径长度是否大于 /(n/) 的厉害负环判法。

精度好像没咋卡我。

#include <bits/stdc++.h>
#define pb push_back
#define db double
using namespace std;
int rd() {
	int sum=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1; ch=getchar();
	}
	while(ch<='9'&&ch>='0') {
		sum=sum*10+ch-'0'; ch=getchar();
	}
	return sum*f;
}
const int N=2005;
const db eps=1e-8;
struct edge {
	int nex,to; db w;
}e[N];
int hea[N],cnt;
int n,m;

void add_edge(int x,int y,db z) {
	e[++cnt].nex=hea[x]; e[cnt].to=y; e[cnt].w=z; hea[x]=cnt;
}

db dis[N];
int ct[N];
bool vis[N];
queue<int>q;
bool check(db W) {
	// e[i].w=-(e[i].w-w)
	W=log2(W);
	for(int i=0;i<=n;i++) dis[i]=0.0,ct[i]=0,vis[i]=0;
	for(int i=1;i<=n;i++) {
		vis[i]=1; q.push(i);
	}
	while(!q.empty()) {
		int x=q.front(); q.pop();
		vis[x]=0;
//		cout<<x<<" "<<dis[x]<<'/n';
		for(int i=hea[x];i;i=e[i].nex) {
			int y=e[i].to; db w=-(e[i].w+W);
//			cout<<x<<" "<<y<<" "<<w<<'/n';
			if(dis[y]>dis[x]+w) {
//				cout<<x<<" "<<y<<" "<<w<<'/n';
				dis[y]=dis[x]+w;
				ct[y]=ct[x]+1;
				if(ct[y]>=n) {
					return 0;
				}
				if(!vis[y]) vis[y]=1,q.push(y);
			}
//			 else if(abs(dis[x]+w-dis[y])<eps&&y==s) {
//				cout<<"asdf";
//				return 0;
//			}
		}
	}
	return 1;
}

signed main() {
	n=rd(); m=rd();
	for(int i=1;i<=m;i++) {
		int a=rd(),b=rd(),c=rd(),d=rd();
//		c/a
		db qwq=log2(c)-log2(a);
//		cout
//		cout<<qwq<<'/n';
		add_edge(b,d,qwq);
	}
	db l=0.0,r=1.0;
	while(r-l>eps) {
		db mid=(l+r)/2.0;
		if(check(mid)) l=mid;
		else r=mid;
	}
	cout<<l;
	return 0;
}

原创文章,作者:,如若转载,请注明出处:https://blog.ytso.com/276528.html

(0)
上一篇 2022年7月24日
下一篇 2022年7月24日

相关推荐

发表回复

登录后才能评论