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;
}
}

浙公网安备 33010602011771号