洛谷 P1416 攻击火星 排版重构
洛谷 P1416 攻击火星
Update
20210307 修复了挂掉的图片
20210307 重构排版
Solution
understand
首先,你弄明白了什么是度吗?
一个点的度,等于与它连接的边的数量。
那这题怎么模拟鸭?50000点,邻接表都开不了耶……
接着,我们从特殊到一般来构造这道题——
special situation
n=1
只有一个点,这个点一定会被删掉,ans=0
n=2
有了两个点,但是度数相同,都会被删掉,ans=0
n=3
样例中也是三个点,使用的是一条链的构造方法。
ans=1
欸?这个链会不会是一个提示?
n=4
我们试试用一条链
也是这样最优,ans=4
难道说链就是正确的构造方法吗?
再试试吧
n=5
继续使用链:
由于删去了两个末端节点后,中间的那个节点的度仍为2。所以它会在d=2时被删去!
有没有一种方法,可以避免这种悲剧的发生呢?
当然有的!我们换一种构造方法。请看好了——
以\(n=6\)为例:
选出两个末端节点------牺牲品
把两个末端节点与所有非末端节点相连
再把非末端节点与所有非末端节点相连(并标上每个点的度)
肯定是两个末端节点先被删除了
但是,当它们被删除时,其他所有的节点都会被改变!
完美的错过当前的d+1
这,就是本题的思想:
删去一些节点后,让其他节点的度都改变为那时的d
这样“其他节点”都不会狗带咯!
general situation
当有n个点时,取其中的两个节点当牺牲品。(所以\(n<2\)时 仍有ans=0
)
把两个末端节点与所有非末端节点相连
再把非末端节点与所有非末端节点相连
最终,
末端节点的度都等于n-2
非末端节点的度都等于n-1(除它本身以外全连)
那么末端节点会先被删除(\(d=n-2\))
同时,非末端节点的度-=2 -> n-3
这时,d++(\(d=n-1\))
非末端节点们就安全了!
如果还是不懂,欢迎评论!
Code
#include<iostream>
using namespace std;
int n;
int main()
{
cin>>n;
if(n==1) cout<<0;
else cout<<n-2;
//也可以是这样的
/*
cout<<max(n-2,0);
*/
return 0;
}