1. 程式人生 > >CF573C Bear and Drawing 構造+樹論

CF573C Bear and Drawing 構造+樹論

mon 2tp lvg 很多 vsr vba char 所有 rii

正解:構造

解題報告:

傳送門!

這題首先可以畫下圖找下規律,,,然後通過找規律可以發現,最終的方案一定是一條主幹+一些枝條,而且這些枝條的分杈一定小於等於2

明確一下主幹的定義,最左邊的節點和最右邊的節點之間的路徑為主幹

如圖

技術分享圖片

強行證明一下吼,,,

因為是兩排平行的“釘子板”

所以如果一個分枝點想要有超過2個兒子結點

因為在同側最多有兩條邊

就一定要往另一邊伸至少一條邊

這樣就因為這條邊擋住了一側(比如說左側)

那麽剩下的邊只能往右側伸展了

那它向另一側伸的邊伸出的子樹中的葉子節點一定有一個是最左邊的節點

那最左邊的節點的路徑一定要經過它

所以它就在最左邊的節點到最右邊的節點的路上

它就是主幹不是分枝辣

然後就考慮,我怎麽找哪個是杈哪個是主幹吶

那就從葉子節點開始,把鏈減下來,剩下的不是主幹就是分杈點

然後就看,如果這個點麻油被減下來的鄰居只有一個,說明那它就是分叉點或者主幹點的最側端

然後最後判斷一下484所有主幹的鄰居主幹點都小於等於2就好辣!

(最後分享一個傻逼錯誤,,,給大家提個醒,,,雖然我jio得不會有人和我一樣蠢地犯這個錯誤QAQ

就是,我jio得這題過程中有很多次要算size,所以我就預處理了下sz存了下來

但是,我是一遍算sz一遍dfs

然後這就會導致,在dfs的時候可能會dfs到還麻油算sz的點

就會錯誤地刪掉

就WA了,,,

我說開始錯的時候找評測記錄怎麽一直沒找到和我一樣WA在第五個點的,,,原來是這個錯誤太sd辣一般人不會犯嗚嗚嗚,,,

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define il inline
#define rg register
#define rp(i,x,y) for(rg ll i=x;i<=y;++i)
#define my(i,x,y) for(rg ll i=x;i>=y;--i)

const ll N=100000
+10; ll n,sz[N],lg[N]; bool del[N]; vector<ll>ed[N]; il ll read() { rg char ch=getchar();rg ll x=0;rg bool y=1; while(ch!=- && (ch>9 || ch<0))ch=getchar(); if(ch==-)ch=getchar(),y=0; while(ch<=9 && ch>=0)x=(x<<3)+(x<<1)+(ch^0),ch=getchar(); return y?x:-x; } il void dfs(ll nw,ll sn){if(sz[nw]<=2){del[nw]=1;rp(i,0,sz[nw]-1)if(ed[nw][i]!=sn)dfs(ed[nw][i],nw);}} int main() { // freopen("cjk.in","r",stdin); // freopen("cjkcjk.out","w",stdout); n=read();rp(i,1,n-1){ll x=read(),y=read();ed[x].push_back(y);ed[y].push_back(x);} rp(i,1,n)sz[i]=ed[i].size();rp(i,1,n)if(sz[i]==1)dfs(i,0); rp(i,1,n)rp(j,0,sz[i]-1)if(del[ed[i][j]])++lg[i]; rp(i,1,n) if(!del[i]) { ll cnt=0; rp(j,0,sz[i]-1)if(sz[ed[i][j]]-min(lg[ed[i][j]],2)>1 && (!del[i]))++cnt; if(cnt>2)return printf("No"),0; } return printf("Yes"),0; }
這兒是代碼!

CF573C Bear and Drawing 構造+樹論