LUOGU P1453 城市環路 基環樹 dp

2022-05-12 10:27:24 字數 1508 閱讀 5014

傳送門

解題思路

一道基環樹上$dp$的題,這種題比較套路吧,首先第一遍$dfs$把環找出來,然後對於環上的每乙個點都向它子樹內做一次樹形$dp$,$f[i][0/1]$表示到了$i$這個點選或不選的最大值,轉移和沒有上司的舞會那道題差不多,就是求乙個帶權最大獨立集。然後再在環上做一次樹形$dp$,$g[i][0/1][0/1]$表示以$i$為根的子樹中$i$選不選,最後一維記錄的是起始節點擊不選,因為終止節點和起始節點只能選乙個,然後就胡亂$dp$一下。

#include#include

#include

#include

#include

#include

using

namespace

std;

const

int maxn = 100005

;inline

intrd()

while(isdigit(ch))

return f?x:-x;

}int

n,p[maxn],head[maxn],cnt,end;

int to[maxn<<1],nxt[maxn<<1

],stk[maxn],top;

double f[maxn][2],ans,g[maxn][2][2

],k;

bool vis[maxn],b[maxn],flag,in

[maxn];

vector

v;inline

void add(int bg,int

ed)void dfs(int x,int

fa) v.push_back(x);

vis[x]=1;flag=1

;

return

; }

b[x]=1;stk[++top]=x;

for(register int i=head[x];i;i=nxt[i])

}void dp_l(int x,int

fa)}

void dp_h(int x,int

fa)

in[u]=1

;dp_h(u,x);

if(u==end)

else

if(end) return

; }

}int

main()

scanf(

"%lf

",&k);

dfs(

1,0);

vector

::iterator it=v.begin();int s=*it;

for(;it0);in[s]=1

; dp_h(s,

0);ans=max(max(g[s][0][0],g[s][1][0]),g[s][0][1

]); printf(

"%.1lf

",ans);

return0;

}

view code

題解 Luogu1453 城市環路

給你一棵樹,強制要求一條邊只能選乙個點,並且還額外給條邊 s t s,t 說s,t也不能同時選,求最大貢獻 這不是擺明了那你用樹形dp切掉的節奏嗎?設f u 0 1 f u 0 1 表示以u u 為根的字樹,u role presentation u u點選或不選的最大貢獻 然後轉移比較顯然,1.如...

洛谷 P1453 城市環路

給出一幅有n個點,n條邊的無向聯通圖,每乙個點有乙個權,並給出乙個常數k,對其中一些點進行染色,且相鄰兩點的顏色不能都染,則最大的染色點權值和 k是多少.首先題目與k幾乎無關 最後乘上即可 僅僅比樹多了一條邊,因而只有乙個環,只要處理一下這個唯一環即可用樹形dp的思路來做.可以在這個環上找任意兩個相...

luogu1453 城市環路 樹形dp

p1453城市環路 最開始是按騎士那道題的做法 只是這道是雙向邊 先dfs一遍判環 根節點一定在環上 然後從根節點出發 強制不選根節點的父親 因為建的是雙向邊dfs來dp的時候會重複算 所以用vis來記錄這個點有沒有走過 然後再來一遍從根節點的父親出發 不選根節點的父親的父親 不知道為啥我第二遍dp...