题解 卷王

传送门

发现 \(|s|>3\) 时无解
发现 \(|s|\leqslant 3\) 时可以分 7 中情况大力分类讨论
核心思路是构造大度数点
懒得展开讨论了

AC code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define pb push_back
#define ll long long
//#define int long long

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++)
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;
int p[N];

namespace force{
	int head[20], fa[20], dsu[20], ecnt, maxlen;
	vector<int> buc[20];
	struct edge{int to, next;}e[40];
	inline void add(int s, int t) {e[++ecnt]={t, head[s]}; head[s]=ecnt;}
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	void dfs2(int u, int fa, int dis) {
		buc[dis].pb(u);
		maxlen=max(maxlen, dis);
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (v==fa) continue;
			dfs2(v, u, dis+1);
		}
	}
	int getp(int u) {
		maxlen=0;
		for (int i=0; i<=n; ++i) buc[i].clear();
		dfs2(u, 0, 0);
		if (buc[maxlen].size()>1) return -1;
		else return buc[maxlen][0];
	}
	void dfs1(int u) {
		if (u>n) {
			for (int i=1; i<=n; ++i) dsu[i]=i;
			int cnt=0;
			for (int i=1; i<=n; ++i) if (fa[i]) dsu[find(fa[i])]=find(i), ++cnt;
			if (cnt!=n-1) return ;
			int t=find(1);
			for (int i=2; i<=n; ++i) if (find(i)!=t) return ;
			memset(head, -1, sizeof(head)); ecnt=0;
			for (int i=1; i<=n; ++i) if (fa[i]) add(fa[i], i), add(i, fa[i]);
			for (int i=1; i<=n; ++i) if (getp(i)!=p[i]) return ;
			puts("Possible");
			for (int i=1; i<=n; ++i) if (fa[i]) printf("%d %d\n", fa[i], i);
			exit(0);
		}
		for (int i=0; i<=n; ++i) if (i!=u) fa[u]=i, dfs1(u+1);
	}
	void solve() {
		dfs1(1);
		puts("Impossible");
		exit(0);
	}
}

namespace task1{
	int uni[N], cnt[N], usiz;
	vector<int> sets, sett, neg;
	void solve() {
		if (n==1) {puts(p[1]==1?"Possible":"Impossible"); exit(0);}
		for (int i=1; i<=n; ++i) uni[++usiz]=p[i];
		sort(uni+1, uni+usiz+1);
		usiz=unique(uni+1, uni+usiz+1)-uni-1;
		if (usiz>3) {puts("Impossible"); exit(0);}
		for (int i=1; i<=n; ++i) if (p[i]==i) {puts("Impossible"); exit(0);}
		for (int i=1; i<=n; ++i) for (int j=1; j<=usiz; ++j) if (p[i]==uni[j]) ++cnt[j];
		if (usiz==1) {
			assert(uni[1]==-1);
			if (n<=3) {puts("Impossible"); exit(0);}
			puts("Possible");
			for (int i=2; i<=n; ++i) printf("1 %d\n", i);
			exit(0);
		}
		else if (usiz==2) {
			if (uni[1]==-1 || uni[2]==-1) {
				int t=(uni[1]==-1)?uni[2]:uni[1];
				for (int i=1; i<=n; ++i)
					if (p[i]==-1) {if (i!=t) neg.pb(i);}
					else sett.pb(i);
				if (neg.size()+1==2 && sett.size()>2) {
					puts("Possible");
					int link=neg.back(); neg.pop_back();
					int t1=sett.back(); sett.pop_back();
					printf("%d %d\n", t, link);
					printf("%d %d\n", link, t1);
					for (auto it:sett) printf("%d %d\n", t1, it);
					exit(0);
				}
				else if (sett.size()<3||neg.size()+1<3) {puts("Impossible"); exit(0);}
				else {
					puts("Possible");
					int linkt=sett.back(); sett.pop_back();
					int link1=neg.back(); neg.pop_back();
					int link2=neg.back(); neg.pop_back();
					printf("%d %d\n", link1, link2);
					printf("%d %d\n", link2, t);
					printf("%d %d\n", link1, linkt);
					for (auto it:sett) printf("%d %d\n", linkt, it);
					for (auto it:neg) printf("%d %d\n", link1, it);
					exit(0);
				}
			}
			else {
				int s=uni[1], t=uni[2];
				if (p[s]!=t || p[t]!=s) {puts("Impossible"); exit(0);}
				for (int i=1; i<=n; ++i)
					if (p[i]==s) {if (i!=t) sets.pb(i);}
					else {if (i!=s) sett.pb(i);}
				if (sets.size()+1==1 && sett.size()+1==1) force::solve();
				else if (sets.size()+1==2 && sett.size()+1==2) force::solve();
				else if (sets.size()+1<3 || sett.size()+1<3) {puts("Impossible"); exit(0);}
				else {
					puts("Possible");
					int s1=sets.back(); sets.pop_back();
					int s2=sets.back(); sets.pop_back();
					int t1=sett.back(); sett.pop_back();
					int t2=sett.back(); sett.pop_back();
					printf("%d %d\n", t, s2);
					printf("%d %d\n", s2, s1);
					printf("%d %d\n", s1, t1);
					printf("%d %d\n", t1, t2);
					printf("%d %d\n", t2, s);
					for (auto it:sets) printf("%d %d\n", s1, it);
					for (auto it:sett) printf("%d %d\n", t1, it);
					exit(0);
				}
			}
		}
		else {
			if (uni[1]!=-1) {puts("Impossible"); exit(0);}
			int s=uni[2], t=uni[3];
			if (p[s]!=t || p[t]!=s) {puts("Impossible"); exit(0);}
			for (int i=1; i<=n; ++i)
				if (p[i]==s) {if (i!=t) sets.pb(i);}
				else if (p[i]==t) {if (i!=s) sett.pb(i);}
				else neg.pb(i);
			if (sets.size()+1==2 && sett.size()+1==2) {
				puts("Possible");
				int s1=sets.back(); sets.pop_back();
				int t1=sett.back(); sett.pop_back();
				int link=neg.back(); neg.pop_back();
				printf("%d %d\n", s, t1);
				printf("%d %d\n", t1, link);
				printf("%d %d\n", link, s1);
				printf("%d %d\n", s1, t);
				for (auto it:neg) printf("%d %d\n", link, it);
				exit(0);
			}
			else if (sets.size()+1>=3 && sett.size()+1>=3) {
				puts("Possible");
				int s1=sets.back(); sets.pop_back();
				int s2=sets.back(); sets.pop_back();
				int t1=sett.back(); sett.pop_back();
				int t2=sett.back(); sett.pop_back();
				int link=neg.back(); neg.pop_back();
				printf("%d %d\n", s, t2);
				printf("%d %d\n", t2, t1);
				printf("%d %d\n", t1, link);
				printf("%d %d\n", link, s1);
				printf("%d %d\n", s1, s2);
				printf("%d %d\n", s2, t);
				for (auto it:neg) printf("%d %d\n", link, it);
				for (auto it:sets) printf("%d %d\n", s1, it);
				for (auto it:sett) printf("%d %d\n", t1, it);
				exit(0);
			}
			else if (sets.size()+1==1 && sett.size()+1==1 && neg.size()==1) {
				puts("Possible");
				printf("%d %d\n", s, neg.back());
				printf("%d %d\n", t, neg.back());
				exit(0);
			}
			else {puts("Impossible"); exit(0);}
		}
	}
}

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

	n=read();
	for (int i=1; i<=n; ++i) p[i]=read();
	//force::solve();
	task1::solve();
	
	return 0;
}
rand.cpp
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define pb push_back
#define ll long long 
//#define int long long 

int n;
int p[N], dis[N];
vector<int> e[N];

void dfs(int u, int fa) {
	for (auto v:e[u]) {
		if (v==fa) continue;
		dis[v]=dis[u]+1;
		dfs(v, u);
	}
}

signed main()
{
	freopen("tree.in", "w", stdout);
	random_device(seed);
    mt19937 rand(seed());
    
    #if 0
	n=rand()%9+1;
	cout<<n<<endl;
	for (int i=2; i<=n; ++i) {
		int fa=rand()%(i-1)+1;
		e[fa].pb(i); e[i].pb(fa);
	}
	for (int i=1; i<=n; ++i) {
		memset(dis, 0, sizeof(dis));
		dfs(i, 0);
		int maxn=0, cnt=0, lst;
		for (int j=1; j<=n; ++j) maxn=max(maxn, dis[j]);
		for (int j=1; j<=n; ++j) if (dis[j]==maxn) ++cnt, lst=j;
		if (cnt>1) p[i]=-1;
		else p[i]=lst;
	}
	for (int i=1; i<=n; ++i) cout<<p[i]<<' '; cout<<endl;
	#endif
	
	int n=rand()%8+1;
	cout<<n<<endl;
	for (int i=1; i<=n; ++i) {
		if (rand()&1) cout<<-1<<' ';
		else cout<<rand()%n+1<<' ';
	} cout<<endl;
	
	return 0;
}
check.cpp
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define pb push_back
#define ll long long 
//#define int long long 

int n;
int p[N], dis[N], dsu[N];
vector<int> e[N];
char s[N], t[N];
inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}

void dfs(int u, int fa) {
	for (auto v:e[u]) {
		if (v==fa) continue;
		dis[v]=dis[u]+1;
		dfs(v, u);
	}
}

//要用暴力check下是否真的无解

signed main()
{
	freopen("tree.in", "r", stdin);
	cin>>n;
	for (int i=1; i<=n; ++i) cin>>p[i];
	freopen("std.out", "r", stdin);
	cin>>t;
	freopen("tree.out", "r", stdin);
	cin>>s;
	assert(s[0]==t[0]);
	if (s[0]=='I') return 0;
	for (int i=1; i<=n; ++i) dsu[i]=i;
	for (int i=1,u,v; i<n; ++i) {
		cin>>u>>v;
		e[u].pb(v); e[v].pb(u);
		dsu[find(u)]=find(v);
	}
	int t=find(1);
	for (int i=2; i<=n; ++i) assert(find(i)==t);
	for (int i=1; i<=n; ++i) {
		memset(dis, 0, sizeof(dis));
		dfs(i, 0);
		int maxn=0, cnt=0, lst;
		for (int j=1; j<=n; ++j) maxn=max(maxn, dis[j]);
		for (int j=1; j<=n; ++j) if (dis[j]==maxn) ++cnt, lst=j;
		int t;
		if (cnt>1) t=-1;
		else t=lst;
		if (t!=p[i]) assert(0);
	}
	
	return 0;
}
posted @ 2022-02-23 16:47  Administrator-09  阅读(1)  评论(0编辑  收藏  举报