BZOJ 1149 風鈴 樹形DP

2022-05-27 01:03:10 字數 1882 閱讀 2315

題目描述的實際是一顆二叉樹,對於每個結點,要麼滿叉,要麼無叉。

對於一種無解的簡單情況,我們搜一遍樹找到最淺的葉子結點1和最深的葉子結點2,如果dep[1]所以現在所有的葉子結點的深度要麼是dep[1]和dep[2].

我們可以把所有結點用node[x]標記狀態。

node[x]=0表示x的子樹下所有葉子結點深度都是dep[2]。 

node[x]=1表示x的子樹下一部分葉子結點深度是dep[1],一部分是dep[2]。

node[x]=2表示x的子樹下所有葉子結點深度都是dep[1]。

現在有,假設x的兒子結點的node值都是1,則一定無解。證明是顯然的。

假設x的左兒子結點node值大於右兒子結點的node值,則ans+1,表示需要操作一次。證明也是顯然的。

另外node值可以通過一次樹形dp得到,所以總複雜度為o(n).

# include # include 

# include

# include

# include

# include

# include

# include

# include

# include

# include

using

namespace

std;

# define lowbit(x) ((x)&(-x))

# define pi acos(-1.0

)# define eps 1e-8

# define mod

1000000007

# define inf

1000000000

# define mem(a,b) memset(a,b,

sizeof

(a))

# define for(i,a,n)

for(int i=a; i<=n; ++i)

# define fo(i,a,n)

for(int i=a; ii)

# define bug puts("h

");# define lch p

<<1

,l,mid

# define rch p

<<1|1,mid+1

,r# define mp make_pair

# define pb push_back

typedef pair

pii;

typedef vector

vi;# pragma comment(linker,

"/stack:1024000000,1024000000")

typedef

long

long

ll;int

scan()

void out(int

a)

if(a>=10) out(a/10

); putchar(a%10+'0'

);}const

int n=100005;//

code begin...

int pos, mi=inf, ma=0, node[n*10], dep[n*10], n, ans, son[n][2

];void dfs1(intx)}

bool dfs2(int

x)

else

}return1;

}int

main ()

dfs1(1);

if (mi1||dfs2(1)==0) puts("-1"

);

else printf("

%d\n

",ans);

return0;

}

view code

BZOJ 1040 騎士(樹形DP)

題意 給出乙個圖,只有乙個環。每個點有乙個權值。選出一些點兩兩不相鄰,使得權值最大?思路 1 找到環。dfs,標記訪問,下乙個節點不是父節點但是已被訪問則這條邊就是環上的兩個點。標記這個邊是我們找到的環邊,並將這兩個點的中乙個設定為root,另乙個我們設為node 2 由於root和node不能同時...

bzoj1487 無歸島 樹形dp

對於題目中的一句話 對於同乙個島上的任意兩個生物,他們有且僅有乙個公共朋友,即對同一島上的任意兩個生物a和b有且僅有乙個生物c既是a的朋友也是b的朋友。我個人以為他是說這乙個島上的點構成乙個環,否則我看不懂樣例中的圖是怎麼符合題意的。果然我是語體教 那麼這句話是說有x個環,這x個環又構成乙個環。這道...

秘密襲擊 BZOJ5250 樹形DP

分析 聽說正解是fft 線段樹合併,然而我並不會.我們來思考其他的方法。我們要求的是連通塊第k大的和 對於某乙個連通塊,對答案的貢獻 val rank.k 我們不好直接算出每個連通塊的rank.k是多少 但我們可以列舉乙個limit for 1 w val rank.k lim的連通塊的個數 就等於...