题解 P5441 【XR-2】伤痕
xht的神仙题解
一,初探问题
首先,我们知道一共需要建造
容易看出,多建双向道对选择方案数的增多是有益的,因此我们将造满
这样的话,有多少单向道呢?
另一方面,我们把任意四个城市放在一起,称为一组。
一个组可能有两种情况:所有城市可以自由相互到达(意味着你可以从任何一个城市出发去向组中任何另一个城市,并且还能回来)或是不然。
显然,国王选出的四个核心城市组成的一组应是上述中的前者(我们就把它称为强连通组吧,反之就是非强连通组)。
对于所有的
对于其中所有的强连通组,都是可行的核心城市选择方案。因此我们应该尽量减少这
二,非强连通组的分类
看以下三张图(球带表城市,黑线为单向道,绿线为双向道,灰线为不确定的道路):
从蓝色球带表的城市进入红色球带表的城市后,便无法回到蓝色球,因此它们都是非强连通组的可能情况。
事实上,不存在一个非强连通组不属于上述三种情况中的一种,因为非强连通组无非就是存在进去却回不来的城市或是根本就进不去的城市,而上述图已经表示了这样城市的全部可能产生原因。
由此我们将非强连通组进行一下分组。
第一类非强连通组:
满足图一情况(一个城市向其它三个城市发单向道)的组为第一类非强连通组。
第二类非强连通组
满足图二情况(其它三个城市向一个城市发单向道)但不满足图一情况的组为为第二类非强连通组。
注意有的组既满足图一又满足图二:
它应为第一类。
第三类非强连通组
满足图三情况(两个城市连双向道,另外两个也连双向道,前两个分别向后两个连单向道)的组为第三类非强连通组。
容易看出这三类组互相没有重叠,这意味这我们成功将非强连通组进行了分类。
接下来我们要尝试尽量减少这三类非强连通组的数量。
三,减少第一类组:用数学来分析
对与一个城市
如果
从而所有的第一类组的数量为
另一方面我们已经知道所有的单向道总数为
现在记
那么我们的问题成为了:
已知
为了解决它,我们先考虑
这样第一类组就会最少。数量为:
接下来考虑第二类组和第三类组。
四,减少第二和第三类组:构造
事实上,一个特别的构造可在完成三中要求的同时将第二类和第三类组降到最少。
问:那么它们两个最少是有多少呢?
答:最少可以没有。
没错,下面这个构造可以保证不出现第二类和第三类组。
下面是这个构造的两个实例:
看上去很有意思,你会发现这两个图形都是中心对称的,保证了
到底是如何构造的呢?
简单的说,就是将
考虑到一个顶点要向外连
构造方法也可说为:一个城市向接下来的
接下来证明一下这个构造方法的一些性质:
1,它满足每个城市向外的单向道数量相等,即 S_1=S_2=...=S_n=\dfrac{n-3}{2}
由构造方法可知每个城市会向接下来的
2,第二类组不会出现。
我们知道,由于一个顶点向外连线中第
一个篮球和两个绿球向红球连单向边,但顺时针方向最前面的篮球也会向两个绿球连单向边,根据“同时满足图一和图二的组为第一类组”可知此为第一类组。
3,第三类组不会出现
第三类组中会出现有两个连着双向道的的城市同时向一个城市连单向道的情况。
但是考虑到一个顶点向外连边中开始的几条才为向外单向道,中间的为双向道,因此 它连向外单向道的顶点 会在顺时针方向上 它连双向道的顶点 的前面,这意味着 双向道的另一边的顶点 无法向 它连单向道的顶点 连单向道,如图:
最后,由于不会出现第二类和第三类组,我们只需将组的总数减去第一类组的数量就可以得到最终答案:
五,代码
#include<iostream>
using namespace std;
int n,c[100][100];
int main()
{
cin>>n;
if (n==1)
{
cout<<0<<endl<<0;
return 0;
}//特判n=1时的情况
cout<<n*(n-3)*(n*n+6*n-31)/48<<endl;
for (int i=1;i<=n;++i)
for (int j=i+1;j<=i+(n+1)/2;++j)
c[i][(j-1)%n+1]=1;
//这里连边时将单向道和双向道一起处理了
//原因是双向道可以看成两条单向道
for (int i=1;i<=n;++i)
{
for (int j=1;j<=n;++j)
cout<<c[i][j]<<" ";
cout<<endl;
}
return 0;
}