ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces 1684G - Euclid Guess(网络流)

2022-06-12 11:03:43  阅读:193  来源: 互联网

标签:dep int Codeforces ret 3t 1684G ec Euclid hd


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有