CF1943C Tree Compass

rgw2010發表於2024-08-13

思路:

考慮往直徑方向想,設直徑的長度為 \(d\)

首先可以注意到一個性質:

  • 每次操作最多隻會覆蓋住直徑的 \(2\) 個點,那麼答案的下界即為 \(\lceil \frac{d}{2} \rceil\)

分類討論一下。

\(d\) 為奇數,則存在唯一的一個直徑中心 \(u\)

  • 那麼答案為 \((u,0),(u,1),\cdots,(u,\lceil \frac{d-1}{2} \rceil)\)

  • 最優次數是 \(\lceil \frac{d}{2} \rceil\) 次。

\(d\) 為偶數,則存在兩個直徑中心 \(u,v\)

  • \(d \bmod 4 = 0\) 時:

    • 那麼答案為 \((u,1),(v,1),(u,3),(v,3),\cdots,(u,\frac{d}{2}-1),(v,\frac{d}{2}-1)\)

    • 最優次數是 \(\frac{d}{2}\)

    • 這樣是兩者是完全錯開的。

  • \(d \bmod 4 = 2\) 時:

    • 那麼答案為 \((u,0),(u,1),\cdots,(u,\frac{2}{d})\)

    • 最優次數是 \(\frac{d}{2}+1\)

這裡證明一下為什麼當 \(d \bmod 4 = 0\) 時不能取到答案的下界。

注意到若 \(x,y\) 能被同時取到當且僅當 \(\operatorname{dis}(x,y)\) 為偶數。

\(L\) 為直徑的一個端點,那麼 \(\operatorname{dis}(L,x)+\operatorname{dis}(L,y)\) 的奇偶性等價於 \(2*(奇數/偶數)+偶數=偶數\)

因為 \(d \bmod 4 = 2\),所以 \(\sum \operatorname{dis}(L,i) = \frac{d \times (d-1)}{2} \bmod 4 = 1\),則這個和式一定不是偶數,故無法達到下界。

時間複雜度為 \(O(TN)\)

完整程式碼:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=2e3+10;
inline ll read(){
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
          f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
inline void write(ll x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	if(x>9)
	  write(x/10);
	putchar(x%10+'0');
}
ll T,n,x,y,id,sum,cnt;
ll a[N],d[N],fa[N];
vector<ll> E[N];
void add(ll u,ll v){
    E[u].push_back(v);
    E[v].push_back(u);
}
void dfs(ll u,ll f){
    for(auto v:E[u]){
        if(v==f)
          continue;
        fa[v]=u;
        d[v]=d[u]+1;
        dfs(v,u);
    }
}
void solve(){
    cnt=0;
    n=read();
    for(int u,v,i=1;i<n;i++){
        u=read(),v=read();
        add(u,v);
    }
    fa[1]=d[1]=sum=0;
    dfs(1,1);
    for(int i=1;i<=n;i++){
        if(d[i]>=sum){
            sum=d[i];
            id=i;
        }
    }
    //cerr<<id<<'\n';
    fa[id]=d[id]=sum=0;
    dfs(id,id);
    for(int i=1;i<=n;i++){
        if(d[i]>=sum){
            sum=d[i];
            id=i;
        }
      //  cerr<<d[i]<<' ';
    }
   // cerr<<'\n';
    while(id){
        a[++cnt]=id;
        id=fa[id];
    }
    if(cnt&1ll){
        x=a[(cnt+1)>>1ll];
        write((cnt+1)>>1ll);
        putchar('\n');
        for(int i=0;i<((cnt+1)>>1ll);i++){
            write(x);
            putchar(' ');
            write(i);
            putchar('\n');
        }
    }
    else{
        x=a[cnt>>1ll],y=a[(cnt>>1ll)+1];
        if(cnt&3ll){
            write((cnt>>1ll)+1);
            putchar('\n');
            for(int i=0;i<=(cnt>>1ll);i++){
                write(x);
                putchar(' ');
                write(i);
                putchar('\n');
            }
        }
        else{
            write(cnt>>1ll);
            putchar('\n');
            for(int i=1;i<(cnt>>1ll);i+=2){
                write(x);
                putchar(' ');
                write(i);
                putchar('\n');
                write(y);
                putchar(' ');
                write(i);
                putchar('\n');
            }
        }
    }
    for(int i=1;i<=n;i++)
      E[i].clear();
}
bool End;
int main(){
    T=read();
    while(T--)
      solve();
	cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
	return 0;
}