CF1391E题解

考虑dfs树求解
dfs树的性质:没有横叉边
考虑随便生成一个dfs树,查看每个节点的最大深度
如果大于\(ceil(\frac{n}{2})\)则显然存在一个节点到根的路径长度大于\(ceil(\frac{n}{2})\),选择path
否则选择pairing。
对于深度相同的点分成一组,设第\(i\)组组成的数组为\(g_i\)
扫描每个\(i\),当\(g_i\)长度为奇数,则pop掉一个元素
然后把每个\(g_i\)内部两两配对
由于是dfs树,一定没有横叉边,所以每一对之间没有边,跨对最多有\(2\)条边。
我自己想到的做法和主流题解完全一样。

#include<bits/stdc++.h>
using namespace std;
#define N 2000010
vector<int>g[N];
int h[N],nxt[N],v[N],ec,vi[N],d[N],f[N],st[N],tp,ss[N],t1;
void add(int x,int y){
	v[++ec]=y;
	nxt[ec]=h[x];
	h[x]=ec;
}
void dfs(int x){
	vi[x]=1;
	g[d[x]].push_back(x);
	for(int i=h[x];i;i=nxt[i])
		if(!vi[v[i]]){
			d[v[i]]=d[x]+1;
			f[v[i]]=x;
			dfs(v[i]);
		}
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			add(x,y);
			add(y,x); 
		}
		d[1]=1;
		dfs(1);
		int mx=0;
		for(int i=1;i<=n;i++)
			mx=max(mx,d[i]);
		if(mx>ceil((double)(n)/2.0)){
			int mp=0;
			puts("PATH");
			for(int i=1;i<=n;i++)
				if(d[i]==mx){
					mp=i;
					break;
				}
			tp=0;
			while(mp){
				st[++tp]=mp;
				mp=f[mp];
			}
			printf("%d\n",tp);
			for(int i=1;i<=tp;i++)
				printf("%d ",st[i]);
			puts("");
		}
		else{
			puts("PAIRING");
			tp=t1=0;
			for(int i=1;i<=n;i++)
				if(g[i].size()%2==1)
					g[i].pop_back();
			for(int i=1;i<=n;i++)
				for(int j=0;j<g[i].size();j+=2){
					st[++tp]=g[i][j];
					ss[++t1]=g[i][j+1];
				}
			printf("%d\n",tp);
			for(int i=1;i<=tp;i++)
				printf("%d %d\n",ss[i],st[i]);
			puts("");
		}
		for(int i=1;i<=n;i++){
			vi[i]=d[i]=h[i]=f[i]=0;
			g[i].clear();
		}
		ec=0;
	}
}
posted @ 2022-08-03 21:18  会赢嘛  阅读(58)  评论(0)    收藏  举报