題目傳送門
【題目大意】
【思路分析】
好的這道題目我在換根dp的部分卡了乙個世紀……所以設狀態真的很重要,我因為狀態設的不好,然後換根的時候就很複雜qaq
我來講一下乙個學長
的做法叭qwq
最後的連線情況是一棵樹,首先我們要發現兩個性質,就是在樹中藍線一定是連線在父子之間,並且連續的一段藍線一定為偶數。
因為藍線是刪除了一條紅線之後加入的,所以不可能存在類似下左圖這種形狀的連線方式,下右圖這種連線方式才是合法的
然後因為每次新增兩根藍線(我們稱這兩根藍線為一組),所以顯然連續的藍線數量必須是偶數。
總體思路是設1為根先dp一遍,然後換根,重要的是如何設狀態可以在換根的時候方便轉移。
我們設$f[x]$表示以$x$為根的子樹的最大分數,注意此時這個子樹可以單獨出來,即子樹中的藍線數量為偶數。
$d[x][0]$結構體記錄與$x$相連的,以$x$為根的子樹中的邊中最大的邊的值和這條邊連線的$x$的兒子,$d[x][1]$記錄次大值及對應的兒子。當然記錄的值保證更優,即記錄下的兒子$y$在下左圖的連線方式比下右圖的連線方式更優。
轉移見**及注釋
【**實現】
1 #include2 #include3 #include4 #include5 #include6 #include7**戳這裡#define g() getchar()
8#define rg register
9#define go(i,a,b) for(rg int i=a;i<=b;i++)
10#define back(i,a,b) for(rg int i=a;i>=b;i--)
11#define db double
12#define ll long long
13#define il inline
14#define pf printf
15#define mem(a,b) memset(a,b,sizeof(a))
16#define e(i,x) for(rg int i=hd[x];i;i=e[i].nxt)
17#define t(i) e[i].to
18#define w(i) e[i].w
19using
namespace
std;
20int
fr()
27while(ch>='
0'&&ch<='
9') w=(w<<1)+(w<<3)+ch-'
0',ch=g();
28return w*q;29}
30const
int n=200002;31
const
int inf=1e9+7;32
intn,ed,hd[n],f[n],ans;
33struct
edgee[n<<1
];36
struct
noded[n][2
];39 il void build(rg int u,rg int v,rg int
w);hd[u]=ed;
41swap(u,v);
42 e[++ed]=(edge);hd[u]=ed;
43return;44
}45 il void update(rg int x,rg int y,rg int
w);47
else
if(w>d[x][1].v) d[x][1]=(node);
48return;49
}50 il void dp(rg int x,rg int
fa) return;59
}60 il void dfs(rg int x,rg int
fa)72
return;73
}74intmain()
82 dp(1,0);ans=-inf;dfs(1,0
);83 pf("
%d\n
",ans);
84return0;
85 }
P3647 連珠線 題解
portal 首先它從遊戲開始到結束,是始終只有乙個連通塊的。對於連紅邊,那就直接連就可以了。對於連藍邊,我們首先需要找到一對有紅邊直接相連的點,然後拆散它們把新點插進去,然後仍然是乙個連通塊。稍微等價理解一下,發現其實就是一次連紅邊是從當前連通塊伸出去乙個點 而連藍邊肯定是一下就有兩條,我們把這次...
P3647 APIO2014 連珠線 換根DP
傳送門 我們通過分析 手動模擬能夠發現,藍線的形態只有兩種 son u 1 u son u 2 和 son u u fa u 對於每乙個節點,要麼是乙個藍線的中點,要麼就是藍線的端點,所以我們設 f u 0 表示 u 為藍線端點時的答案,f u 1 表示 u 作為中點時的答案 轉移方程如下 f u ...
Luogu P1208 混合牛奶
這個題目直接開個結構體按 排序,然後一直加加加,就可以了。典型的貪心。include include include include include include using namespace std int i,m,n,j,k,ans struct mana 5001 bool cmp man...