题意:给出一个 \(n\) 个结点的树,问如何选择结点进行连线使得结点\(1\)到其他所有结点的最短距离都小于等于 \(2\) 。
题解:这道题倒是自己想出来了。
首先有个结论:连线都是从结点1向其他结点连线,因为这样总是最优的。
由题意可知,当结点\(1\)向某个节点 \(u\) 连线后,与结点 \(u\) 直接相连的所有结点都能满足条件。
考虑树形dp。
\(d[u][0]\):结点u的子结点都满足条件,但是结点u不满足
\(d[u][1]\):结点u的子树(包括 \(u\) 自己)都满足条件,但结点u没有被连线
\(d[u][2]\):结点u的子树(包括 \(u\) 自己)都满足条件,且结点u与节点1连线
那么,对于叶子结点:
\(d[u][0]=0,d[u][1]=inf,d[u][2]=1\)
对于非叶子结点 \(u\) 和它的子结点\(v\):
\(d[u][0]=\sum d[v][1];\)
\(d[u][2]=\sum min(d[v][0],min(d[v][1],d[v][2]))+1\)
\(d[u][1]=\sum min(d[v][1],d[v][2]);\) //在这个式子中必须保证有至少一个子结点\(v\) 取的是 \(d[v][2]\) 。
代码:
#include#include #include #include #include #include #include using namespace std;#define rep(i,a,n) for (int i=a;i =a;i--)#define pb push_back#define fi first#define se second#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<