CF1391E Pairs of Pairs
阿新 • • 發佈:2020-08-10
好神仙的一道題,考後想了很久也沒想出來。
考慮對原圖隨便跑一個 \(dfs\) 樹出來。記 \(dep_i\) 為點 \(i\) 的深度,\(K=\lceil\frac{n}{2}\rceil\)。
- 如果有 \(\forall dep_i\geq K\),那麼我們就找到了一條長度大於等於 \(K\) 的路徑,直接輸出即可。
- 否則,我們把所有點按照 \(dep_i\) 的取值分類(相同的 \(dep_i\) 分為一類),在每一類裡取出 \(\lfloor \frac{cnt_i}{2}\rfloor\) 對點(任意配對,其中 \(cnt_i\) 表示深度為 \(i\) 的點的個數)。下面證明這樣分組後,任意兩組拼在一起的子圖中邊的條數 \(\leq 2\)
程式碼:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int N=1000009; int head[N],cnt,n,m,dep[N],K,id[N],flag,F[N],vis[N],ans1[N],ans2[N]; struct Edge { int nxt,to; }g[N*2]; void add(int from,int to) { g[++cnt].nxt=head[from]; g[cnt].to=to; head[from]=cnt; } void init() { scanf("%d %d",&n,&m);K=n+1>>1; cnt=0; for (int i=1;i<=n;i++) F[i]=dep[i]=head[i]=vis[i]=0; for (int x,y,i=1;i<=m;i++) scanf("%d %d",&x,&y), add(x,y),add(y,x); } void dfs(int x,int fa) { if(flag) return; vis[x]=1; for (int i=head[x];i;i=g[i].nxt) { int v=g[i].to; if(v==fa||vis[v]) continue; dep[v]=dep[x]+1,F[v]=x; if(!flag&&dep[v]>=K-1) { puts("PATH"); printf("%d\n",K); while(v) printf("%d ",v),v=F[v]; puts(""); flag=1; } dfs(v,x); } } bool cmp(int a,int b) { return dep[a]<dep[b]; } void work() { int T; scanf("%d",&T); while(T--) { init(); flag=0; dfs(1,-1); if(!flag) { puts("PAIRING"); int tot=0; for (int i=1;i<=n;i++) id[i]=i; sort(id+1,id+1+n,cmp); for (int i=1;i<=n;i++) if(dep[id[i]]==dep[id[i+1]]) ans1[++tot]=id[i],ans2[tot]=id[i+1],i++; printf("%d\n",tot); for (int i=1;i<=tot;i++) printf("%d %d\n",ans1[i],ans2[i]); } } } int main() { work(); return 0; }