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