Loading

[CF1019C] Sergey's problem 做题记录

小清新构造题,会就会,不会就不会。

link

注意到走两步很特殊,尝试从走一步拼出来,考虑归纳法:

  • 随便选择一个点 \(x\),然后删掉 \(x\) 和所有 \(y\) 满足存在边 \((x, y)\)

  • 设剩下的图的答案集合为 \(S\),若不存在 \(z\in S\) 满足存在边 \((z, x)\),则将 \(x\) 加入 \(S\)

  • 否则 \(z\) 可以覆盖到 \(x\) 和所有 \(y\)(走两步覆盖两个走一步)。

时间复杂度 \(\mathcal O(n + m)\)

  • 启示:这题很困难,首先是观察这个“走两步”的特点,可以拆成两个走一步;其次是直接套用归纳法,归纳 / 增量 构造是非常常用的构造方法。
点击查看代码
#include <bits/stdc++.h>

namespace Initial {
	#define ll int
	#define ull unsigned long long
	#define fi first
	#define se second
	#define mkp make_pair
	#define pir pair <ll, ll>
	#define pb push_back
	#define i128 __int128
	using namespace std;
	const ll maxn = 1e6 + 10, inf = 1e9, mod = 998244353;
	ll power(ll a, ll b = mod - 2, ll p = mod) {
		ll s = 1;
		while(b) {
			if(b & 1) s = 1ll * s * a %p;
			a = 1ll * a * a %p, b >>= 1;
		} return s;
	}
	template <class T>
	const inline ll pls(const T x, const T y) { return x + y >= mod? x + y - mod : x + y; }
	template <class T>
	const inline void add(T &x, const T y) { x = x + y >= mod? x + y - mod : x + y; }
	template <class T>
	const inline void chkmax(T &x, const T y) { x = x < y? y : x; }
	template <class T>
	const inline void chkmin(T &x, const T y) { x = x > y? y : x; }
} using namespace Initial;

namespace Read {
	char buf[1 << 22], *p1, *p2;
	// #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, (1 << 22) - 10, stdin), p1 == p2)? EOF : *p1++)
	template <class T>
	const inline void rd(T &x) {
		char ch; bool neg = 0;
		while(!isdigit(ch = getchar()))
			if(ch == '-') neg = 1;
		x = ch - '0';
		while(isdigit(ch = getchar()))
			x = (x << 1) + (x << 3) + ch - '0';
		if(neg) x = -x;
	}
} using Read::rd;

ll n, m; vector <ll> to[maxn], res;
bool vis[maxn], chs[maxn];

int main() {
	rd(n), rd(m);
	for(ll i = 1; i <= m; i++) {
		ll u, v; rd(u), rd(v);
		to[u].pb(v);
	}
	for(ll i = n; i; i--) {
		if(vis[i]) continue;
		vis[i] = chs[i] = true;
		for(ll j: to[i]) vis[j] = true;
	} memset(vis, false, sizeof vis);
	for(ll i = 1; i <= n; i++)
		if(chs[i] && !vis[i]) {
			res.pb(i);
			for(ll j: to[i]) vis[j] = true;	
		}
	printf("%d\n", (ll) res.size());
	for(ll x: res) printf("%d ", x); puts("");
	return 0;
}
posted @ 2025-01-10 21:04  Sktn0089  阅读(14)  评论(0)    收藏  举报