其他分享
首页 > 其他分享> > Codeforces 1684G - Euclid Guess(网络流)

Codeforces 1684G - Euclid Guess(网络流)

作者:互联网

Codeforces 题面传送门 & 洛谷题面传送门

煞笔题,我是什么煞笔,在这么煞笔的比赛中没有做出这么煞笔的题?

(u1s1 其实感觉这道题还挺有意思的)

首先对于一个数 \(t\),要想得到 \(t\) 为余数,除数至少是 \(t+1\),这样 \(a\) 就至少是 \(2t+1\),因此如果存在 \(2t_i+1>m\) 就直接输出 \(-1\) 好了。我们还可以发现,对于一个满足 \(3t\le m\) 的数,我们可以通过直接构造 \((3t,2t)\) 将其消去并且不会影响到其他数,但是对于 \(3t>m\) 的数就不能这样构造了。换而言之,要想消掉一个 \(3t>m\) 的 \(t\),我们需要选择一个 \(k\) 使得 \(2t+k\le m\),并构造 \((2t+k,t+k)\),这样可以消掉 \(t\) 并进而对 \((t,k)\) 进行辗转相除。因此我们可以想到一个很自然的想法:先用 \(3t\le m\) 的小 t 消去 \(3t>m\) 的大 t,剩余的小 t 直接 \((3t,2t)\) 带走。

但是对于一个大 t 我们又该选择怎样的 \(k\) 呢?贪心?好像没法贪。不过我们注意到一个性质,就是最终 \(\gcd(t,k)\) 肯定会在辗转相除得到的序列中,因此我们不妨就令 \(k=\gcd(t,k)\),即 \(k\mid t\),这样会恰好消除 \(k,t\) 两个数,感性理解这样肯定最优,因此我们考虑在符合 \(t_j\mid t_i\),\(3t_i>m,3t_j\le m\) 的 \(i,j\) 之间连边,然后跑最大匹配,由于是二分图,最大匹配容易求得,如果最大匹配不等于大 t 数量则无解,否则根据前面的过程构造出解即可。

const int MAXN = 1e3;
const int MAXE = 2e6;
const int INF = 0x3f3f3f3f;
int n, m, a[MAXN + 5];
int S, T, hd[MAXN + 5], to[MAXE + 5], nxt[MAXE + 5], cap[MAXE + 5], ec = 1;
void adde(int u, int v, int f) {
	to[++ec] = v; cap[ec] = f; nxt[ec] = hd[u]; hd[u] = ec;
	to[++ec] = u; cap[ec] = 0; nxt[ec] = hd[v]; hd[v] = ec;
}
int dep[MAXN + 5], now[MAXN + 5];
bool getdep(int S, int T) {
	memset(dep, -1, sizeof(dep)); queue<int> q;
	q.push(S); dep[S] = 0;
	while (!q.empty()) {
		int x = q.front(); q.pop(); now[x] = hd[x];
		for (int e = hd[x]; e; e = nxt[e]) {
			int y = to[e], z = cap[e];
			if (z && dep[y] == -1) {
				dep[y] = dep[x] + 1;
				q.push(y);
			}
		}
	}
	return ~dep[T];
}
int getflow(int x, int f) {
	if (x == T) return f; int ret = 0;
	for (int &e = now[x]; e; e = nxt[e]) {
		int y = to[e], z = cap[e];
		if (z && dep[y] == dep[x] + 1) {
			int w = getflow(y, min(f - ret, z));
			cap[e] -= w; cap[e ^ 1] += w; ret += w;
			if (ret == f) return ret;
		}
	}
	return ret;
}
int dinic() {
	int ret = 0;
	while (getdep(S, T)) ret += getflow(S, INF);
	return ret;
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		if (2 * a[i] + 1 > m) return puts("-1"), 0;
	}
	T = (S = n + 1) + 1;
	int cnt = 0;
	for (int i = 1; i <= n; i++) if (3ll * a[i] > m) {
		for (int j = 1; j <= n; j++) if (3ll * a[j] <= m && a[i] % a[j] == 0 && 2ll * a[i] + a[j] <= m)
			adde(i, j, 1);
		cnt++;
	}
	for (int i = 1; i <= n; i++) {
		if (3ll * a[i] > m) adde(S, i, 1);
		else adde(i, T, 1);
	}
	if (dinic() != cnt) return puts("-1"), 0;
	vector<pii> res;
	for (int i = 1; i <= n; i++) if (3ll * a[i] > m) {
		for (int e = hd[i]; e; e = nxt[e]) {
			int y = to[e];
			if (to[e] != S && !cap[e]) res.pb(mp(2 * a[i] + a[y], a[i] + a[y]));
		}
	}
	for (int i = 1; i <= n; i++) if (3ll * a[i] <= m) {
		for (int e = hd[i]; e; e = nxt[e]) {
			int y = to[e];
			if (y == T && cap[e]) res.pb(mp(3 * a[i], 2 * a[i]));
		}
	}
	printf("%d\n", (int)(res.size()));
	for (pii p : res) printf("%d %d\n", p.fi, p.se);
	return 0;
}

标签:dep,int,Codeforces,ret,3t,1684G,ec,Euclid,hd
来源: https://www.cnblogs.com/ET2006/p/Codeforces-1684G.html