【SSLGZ 2681】2017年8月11日提高组T3 难题

问题描述
我们有一个n个点的图,现在我们要给这个图加上m条无向边,定义dist(i,j)为i和j之间的最短距离,当然如果这两个点不联通,那么dist(i,j)=n,然后我们定义一个图的大小为所有点对的dist之和,现在我们想要求这个图的最小大小,你可以吗?
输入
第一行是一个正整数T,表示T组数据
接下来T行每行两个正整数表示n,m
输出
输出一个数,表示答案。
样例输入
1
4 5
样例输出
14
算法讨论
考虑贪心地一条一条边添加进去。
当 m≤n−1 时,我们需要最小化距离为 n 的点对数,所以肯定是连出一个大小为 m+1 的联通块,剩下的点都是孤立点。在这个联通块中,为了最小化内部的距离和,肯定是连成一个菊花的形状,即一个点和剩下所有点直接相邻。
当 m > n-1 时,肯定先用最开始 n-1条边连成一个菊花,这时任意两点之间距离的最大值是 2。因此剩下的每一条边唯一的作用就是将一对点的距离缩减为 1。
这样我们就能知道了最终图的形状了,稍加计算就能得到答案。要注意 m 有可能大于n(n−1)/2

#include <cstdio>
#include <iostream>
using namespace std;
long long n,t;
long long m,s;

int main()
{
    cin>>t;
    for (int k=1;k<=t;k++)
    {
        cin>>n>>m;
        s=0;
        if (m<n-1)
        {
            s=(n-1-m)*(n-1)*n*2;
            s=s+m*2;
            s=s+m*4;
        }
        if (m>n*(n-1)/2)
            m=n*(n-1)/2;
        if (m==n*(n-1)/2)
            s=m*2;
        if (m>n-1 && m<n*(n-1)/2)
        {
            s=m*2;
            s=s+((n*(n-1)/2)-m)*4;
        }
        cout<<s<<endl;
    }
    return 0;
}

这里写图片描述
Pixiv ID:48119465

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值