Live2D

【UR #2】跳蚤公路 题解

link

Solution

md,早就把 Bell-Manford 忘干净了,一直在想着用 floyd 判负环。😢

首先排除 SPFA。然后发现 floyd 直接复杂度爆炸。我们考虑Bell-Maxford。我们假设已经确定了 \(x\),设 \(f(i,u)\) 表示走了 \(i\) 步到 \(u\),如果 \(u\) 在一个负环上,那我们存在 \(f(n,u)<f(n-1,u)\)。考虑到这个题目里面我们的 \(x\) 很大,所以我们只能记录 \(\sum c\)\(c\) 即是每条边的种类),那么即是设 \(f(i,u,s)\) 表示走了 \(i\) 步到 \(u\)\(\sum c=s\) 的最小权值之和。

对于 \(u\) 判断的话即是:

\[\min(kx+f(n,u,k))<\min(jx+f(n-1,u,j)) \]

如果存在 \(k-j>0\) 的话我们可以得到

\[x<\frac{f(n-1,u,j)-f(n,u,k)}{k-j} \]

\(k-j<0\) 的时候,可以发现会提供一个下界。那么对于 \(u\) 就会提供一个区间 \((l,r)\) 表示不能取到这里面。

那么我们在对于 \(u\) 考虑答案的时候只需要把所有能到它的集合取交即可。

复杂度大抵是 \(\Theta(n^3\log n+n^2m)\) 的。

Code

#include <bits/stdc++.h>
using namespace std;
     
#define Int register int
#define inf 0x3f3f3f3f3f
#define int long long
#define MAXM 10005
#define MAXN 105

// char buf[1<<21],*p1=buf,*p2=buf;
// #define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,m,F[MAXN][MAXN][MAXN << 1];
int &f (int i,int u,int j){return F[i][u][j + n + 2];}

struct edge{
	int v,w,s,nxt;
}e[MAXM];
int toop = 1,head[MAXN];

void add_edge (int u,int v,int w,int s){
	e[++ toop] = edge{v,w,s,head[u]},
	head[u] = toop;
}

bool achi[MAXN][MAXN];

#define pii pair<int,int>
#define se second
#define fi first
vector <pii> seq[MAXN];

signed main(){
	read (n,m);
	for (Int i = 1;i <= n;++ i) achi[i][i] = 1;
	for (Int i = 1;i <= m;++ i){
		int u,v,w,s;read (u,v,w,s);
		add_edge (u,v,w,s),achi[u][v] = 1;
	}
	for (Int k = 1;k <= n;++ k)
		for (Int i = 1;i <= n;++ i)
			for (Int j = 1;j <= n;++ j) achi[i][j] |= achi[i][k] & achi[k][j];
	for (Int u = 1;u <= n;++ u)
		for (Int s = -n;s <= n;++ s) f (0,u,s) = inf;
	f (0,1,0) = 0;
	for (Int t = 1;t <= n;++ t){
		for (Int u = 1;u <= n;++ u)
			for (Int s = -n;s <= n;++ s) f (t,u,s) = f (t - 1,u,s);
		for (Int u = 1;u <= n;++ u)
			for (Int s = -n;s <= n;++ s){
				for (Int i = head[u];i;i = e[i].nxt){
					int v = e[i].v,k = e[i].s,w = e[i].w;
					if (f (t - 1,u,s) == inf) continue;
					chkmin (f (t,v,s + k),f (t - 1,u,s) + w);
				}
			}
	}
	for (Int u = 1;u <= n;++ u)
		for (Int i = -n;i <= n;++ i){
			if (f (n,u,i) >= f (n - 1,u,i)) continue;
			int L = -inf,R = inf;
			for (Int j = -n;j <= n;++ j){
				if (i == j || f (n - 1,u,j) == inf) continue;
				if (j < i) chkmin (R,(int)ceil ((f (n - 1,u,j) - f (n,u,i)) * 1.0 / (i - j)));
				else chkmax (L,(int)floor ((f (n - 1,u,j) - f (n,u,i)) * 1.0 / (i - j)));
			}
			if (L < R) seq[u].push_back ({L,R});
		}
	for (Int u = 1;u <= n;++ u){
		vector <pii> sta;
		for (Int v = 1;v <= n;++ v) if (achi[1][v] && achi[v][u])
			for (pii it : seq[v]) sta.push_back (it);
		if (sta.empty()){puts ("-1");continue;}
		sort (sta.begin(),sta.end());
		int L = inf,R = -inf,las = -inf;bool chk = 0;
		int mxr = -inf;for (pii it : sta) chkmax (mxr,it.se);
		if (mxr != inf){puts ("-1");continue;}
		for (Int i = 0;i < sta.size();++ i){
			if (!i && sta[i].fi != -inf){L = -inf,R = sta[i].fi,chk = 1;break;}
			if (las != -inf && las <= sta[i].fi){L = las,R = sta[i].fi,chk = 1;break;}
			chkmax (las,sta[i].se);
		}
		if (!chk && las != inf) R = inf;
		if (L == -inf || R == inf) puts ("-1");
		else if (L > R) puts ("0");
		else write (R - L + 1),putchar ('\n');
	}
	return 0;
}
posted @ 2022-11-07 22:56  Dark_Romance  阅读(27)  评论(0编辑  收藏  举报