[簡單思維] 題解 ThREE
阿新 • • 發佈:2020-11-04
[簡單思維] 題解 ThREE
這題自己沒有獨立想出來啊啊啊啊啊。
題目分析
首先考慮何時滿足 \(p_i+p_j\equiv 0\pmod 3\) 或者 \(p_i\times p_j\equiv 0\pmod 3\) ,如果 \(p_i\bmod 3=0\) 或者 \(p_j\bmod 3=0\) 時顯然滿足,否則 \(p_i\bmod 3=1\) 並且 \(p_j\bmod 3=2\) 或 \(p_i\bmod 3=2\) 並且 \(p_j\bmod 3=1\) ,類似二分圖,但是不允許我們連完所有邊 \((i,j)\) ( \(\mbox{dis}(i,j)=3\) )後二分圖染色,如果直接在樹上面進行二分圖染色,那麼也滿足 \(i,j(\mbox{dis}(i,j)=3)\)
假設黑色節點數量為 \(b\) ,白色節點數量為 \(w\) ,分類討論:
- 如果 \(b>\lfloor\frac{n}{3}\rfloor\) 並且 \(w> \lfloor\frac{n}{3}\rfloor\) ,此時必然可以將所有模 \(3\) 為 \(1\) 的數分配給黑色節點,所有模 \(3\) 為 \(2\) 的數分配給白色節點,剩下的數模 \(3\) 為 \(0\) ,就可以任意分配了。
- 如果 \(b\le \lfloor\frac{n}{3}\rfloor\) ,此時就可以給所有黑色節點分配到模 \(3\) 為 \(0\)
- 如果 \(w\le \lfloor\frac{n}{3}\rfloor\) ,和 \(b\le \lfloor\frac{n}{3}\rfloor\) 一樣。
我自己主要是 \(b\le \lfloor\frac{n}{3}\rfloor\) 的情況沒有想到如何處理。
參考程式碼
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ch() getchar() #define pc(x) putchar(x) using namespace std; template<typename T>void read(T&x){ static char c;static int f; for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f; for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f; } template<typename T>void write(T x){ static char q[65];int cnt=0; if(x<0)pc('-'),x=-x; q[++cnt]=x%10,x/=10; while(x) q[++cnt]=x%10,x/=10; while(cnt)pc(q[cnt--]+'0'); } const int maxn=200005; struct Edge{ int v,nt; Edge(int v=0,int nt=0): v(v),nt(nt){} }e[maxn*2]; int hd[maxn],num; void qwq(int u,int v){ e[++num]=Edge(v,hd[u]),hd[u]=num; } int B,W,dp[maxn]; void dfs(int u,int fa){ if(dp[u]&1)++B;else ++W; for(int i=hd[u];i;i=e[i].nt){ int v=e[i].v; if(v==fa)continue; dp[v]=dp[u]+1;dfs(v,u); } } int p[maxn],vis[maxn]; int main(){ int n;read(n); for(int i=1;i<n;++i){ int u,v; read(u),read(v); qwq(u,v);qwq(v,u); } dfs(1,0);int nd3=n/3; if(B>nd3&&W>nd3){ int n1=1,n2=2,n3=3; for(int i=1;i<=n;++i){ if(dp[i]&1){ if(n1<=n)p[i]=n1,n1+=3; else p[i]=n3,n3+=3; } else{ if(n2<=n)p[i]=n2,n2+=3; else p[i]=n3,n3+=3; } } } else{ int spe=(B>W),n3=3; for(int i=1;i<=n;++i){ if((dp[i]&1)^spe){ p[i]=n3;vis[n3]=true;n3+=3; } } int no=1; for(int i=1;i<=n;++i){ if(!((dp[i]&1)^spe)){ while(vis[no])++no;p[i]=no;++no; } } } for(int i=1;i<=n;++i) write(p[i]),pc(" \n"[i==n]); return 0; }