题解 ladice

传送门

将每个物品看成一条无向边,则存在一种合法方案的条件是每个连通块都是一棵树或是基环树
并查集判断即可

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 300010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, l;
int a[N], b[N];

namespace force{
	int bel[N];
	bool vis[N];
	bool dfs(int u, int num) {
		vis[u]=1;
		if (!bel[u]) {bel[u]=num; vis[u]=0; return 1;}
		int now=bel[u], other=a[now]==u?b[now]:a[now];
		if (!vis[other] && dfs(other, now)) {bel[u]=num; vis[u]=0; return 1;}
		else {vis[u]=0; return 0;}
	}
	void solve() {
		for (int i=1; i<=n; ++i) {
			if (!bel[a[i]]) {bel[a[i]]=i; puts("LADICA");}
			else if (!bel[b[i]]) {bel[b[i]]=i; puts("LADICA");}
			else {
				if (dfs(a[i], i)) puts("LADICA");
				else if (dfs(b[i], i)) puts("LADICA");
				else puts("SMECE");
			}
		}
		exit(0);
	}
}

namespace task1{
	int dsu[N], siz[N], esiz[N];
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	inline void uni(int s, int t) {s=find(s); t=find(t); dsu[s]=t; siz[t]+=siz[s]; esiz[t]+=esiz[s];}
	void solve() {
		for (int i=1; i<=l; ++i) dsu[i]=i, siz[i]=1;
		for (int i=1; i<=n; ++i) {
			int f1=find(a[i]), f2=find(b[i]);
			// cout<<f1<<' '<<f2<<endl;
			if (f1==f2) {
				if (esiz[f1]<siz[f1]) ++esiz[f1], puts("LADICA");
				else puts("SMECE");
			}
			else {
				if (!(esiz[f1]==siz[f1]&&esiz[f2]==siz[f2])) {
					uni(f1, f2);
					++esiz[find(a[i])];
					puts("LADICA");
				}
				else puts("SMECE");
			}
		}
		exit(0);
	}
}

signed main()
{
	freopen("ladice.in", "r", stdin);
	freopen("ladice.out", "w", stdout);

	n=read(); l=read();
	for (int i=1; i<=n; ++i) a[i]=read(), b[i]=read();
	// force::solve();
	task1::solve();

	return 0;
}
posted @ 2021-11-19 14:33  Administrator-09  阅读(0)  评论(0编辑  收藏  举报