Codeforces Round #745 (Div. 2)
题意
给出n,m,k。判断是否存在一个由n个结点,m条边组成的最大直径小于k - 1的无向图。
- 直径:所有结点中最大的两个结点之间的距离
- 距离:两个结点之间最短的路径(假设所有的边权值为1)
思路
- 如果 m < n − 1 ∣ ∣ m > n ( n − 1 ) / 2 m < n - 1 ~||~ m > n (n - 1) / 2 m<n−1 ∣∣ m>n(n−1)/2 ,明显无法形成图(我也不太清楚为什么 m < n − 1 m < n - 1 m<n−1不可以,如果这样的话,则会有独立的点存在)
- 如果 n = 1 , m = 0 n = 1,m = 0 n=1,m=0, 只有当 k > 1 k > 1 k>1 时才可以
- 如果 m = n ( n − 1 ) / 2 m = n (n - 1)/2 m=n(n−1)/2,明显,这是个完全图(不清楚完全图的查查。观察公式就可以发现结论是公差为1,首项为1的等差数列前n和,其实就是任何两个结点之间都存在直接相连的边,)。则图的直径为1,则 k > 2 k > 2 k>2即可。
- 如果 m = n − 1 m = n - 1 m=n−1,要使图的直径最小,这应该以一个结点为中心,其他结点应该以这个结点为圆心分别与之直接相连(就是菊花的形状),此时图的直径为2。则只需满足 k > 3 k > 3 k>3 即可。
- 如果
n
−
1
<
m
<
n
(
n
−
1
)
/
2
n - 1 < m < n(n - 1) / 2
n−1<m<n(n−1)/2,则可以在上图(菊花)的基础上连接其他的结点,但是图的直径不会大于2。但由于不是完全图,则图的直径大于1。则只需满足
k
>
3
k > 3
k>3 即可。
(其实4,5可以合并为一条结论) - 综上:
{ m < n − 1 ∣ ∣ m > n ( n − 1 ) / 2 NO n = 1 , m = 0 , k > 1 YES m = n ( n − 1 ) / 2 , k > 2 YES n − 1 ≤ m < n ( n − 1 ) / 2 , k > 3 YES o t h e r s c o n d i t i o n s NO \begin{cases} m < n - 1~||~m > n(n - 1)/2& \text{NO}\\ n = 1, m = 0, k > 1& \text{YES}\\ m = n(n - 1)/2, k > 2& \text{YES}\\ n - 1\leq m < n(n - 1)/2, k > 3& \text{YES}\\ others~conditions& \text{NO}\end{cases} ⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧m<n−1 ∣∣ m>n(n−1)/2n=1,m=0,k>1m=n(n−1)/2,k>2n−1≤m<n(n−1)/2,k>3others conditionsNOYESYESYESNO
代码
IOS;
int T; cin >> T;
while (T--)
{
ll n, m, k; cin >> n >> m >> k;
int f;
if (n == 1 && m == 0 && k > 1) f = 1;
else if (m < n - 1 || m > n * (n - 1) / 2) f = 0;
else if (m == n * (n - 1) / 2 && k > 2) f = 1;
else if (m >= n - 1 && m < n * (n - 1) / 2 && k > 3) f = 1;
else f = 0;
if (f) cout << "YES\n";
else cout << "NO\n";
}
最后:真是狗日的分类讨论。真佩服那些比赛时写出来的人。