(题目链接在这儿!)
题目描述
一群外星人将要攻击火星。
火星的地图是一个n个点的无向图。这伙外星人将按照如下方法入侵,先攻击度为0的点(相当于从图中删除掉它),然后是度为1的点,依此类推直到度为n-1的点。
所有的点度统计是动态统计的。(一个点删掉后,与之相连的点的点度都会-1)。外星人攻击度为某个数的点时是同时攻击的。
你需要设计这个图的边的方案来使得未被攻击的点最多。
输入格式
输入文件包含一行一个整数n。
输出格式
一行一个整数,表示最多的最后未被攻击的点。
输入输出样例
3
1
说明/提示
【样例解释】
①-②-③,这样首先删掉度为1的①和③,此时②度数为0,不会被删去。
【数据范围】
对于20%的数据1<=n<=10
对于100%的数据1<=n<=50000
思路:
大家看了这道题,是不是有一点懵逼的感觉?
n<=50000?! 这建图至少要二维数组呀!
还有,这O(n2)算法过不了啊!
但是,当你看到代码时,你肯定会认为:
你这几年的数学白学了吧!
(提示:算法标签为模拟与构造)
(建议你想一想再看代码,因为这是一道普及-的题目!)
(我说这题O(1)你们信吗?)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int main() 5 { 6 cin>>n; 7 if(n==1) cout<<0; 8 else cout<<n-2; 9 return 0; 10 }
(看了代码心情怎么样?)
下面我们就具体证明一下:
若n==1或n==0,则显然,ans=0;
当n==2时,则也显然,ans=0;
当n==3时,要么你让他们变成一个三角形,要么你让他们变成一条线。
显然一条线更优,所以ans=1;
当n>=4时,假设ans==n-1(显然ans<n),
因为最开始总会删除一个或多个点,所以你必须删除一个点且让其他所有的点的度都减1,让其他的点防止被删除。
所以你必须将那个要被删除的点与其他所有的相连,以达到目的。
但这个点的度就变成了n-1,所以它的度一定==max(度)。
这说明要么第一个删的不是它,要么它和其他一个或多个点一起删掉。
显然,与假设时的条件不符,矛盾。
所以假设不成立。
所以我们考虑ans==n-2;(这时若ans可以等于n-2的话,就一定是最优解)
当n==4时(n==3和n==2的情况我们已知符合ans==n-2),你可以如下图,用一条线,删除两边的端点。
所以ans==2==n-2;
当n==5时,你可以像下图一样,构造一个五边形,然后选一个点,与不与它相邻的两个点相连。
当n>=6时,我们可以将n个点分成两种点,第一种有2个点,第二种有n-2个点。
因为n>=6,所以n-2>=4。
我们将所有属于第二种的n-2个点围成一个n-2边形并将所有的对角线以及n-2条边连接。(以下的图都以n==6为例)
这时,在第二种点当中,每一个点都与其他n-3个点连接,所以他们的度都为n-3;
然后,我们再让剩下第一种的两个点与那n-2个点连接。
这时我们就会先将第一种的两个点删除。
于是原图就变成了这样:
这时我们发现,已经不需要删点了。所以结束,ans==n-2,符合规律。
本人总结:
这一题的难点就在要发现规律,自己如果在数据的枚举以及个人的感觉上认为是对的,就应该竭力去验证(本人简称“瞎蒙乱猜法”)。
怎么样? 涨知识了吧!!!