2017多校5 1006 Rikka with Graph

来源:互联网 发布:java system.gc 编辑:程序博客网 时间:2024/06/16 22:30

http://acm.hdu.edu.cn/showproblem.php?pid=6090



很简单的一道题,因为自己不够贪心所以还是细节漏了点。

给出n个点m条边,去把n个点连起来,边不够的话也可以连,只不过权值变成了n,正常的边权值等于该2点间的边的数量,求从map[1][1]到map[n][n]的和最小。

因为m条边不一定全用完,那么肯定2个点最多只会连1条边,因为数据特别大,所以肯定是有公式的,既然有公式,那么图就一定很好算,很容易就能想到图是一个从1个点想四周去延展的网状图,那么就很简单了,从中心点到四周都是1,从四周到其他四周点,都是2,这是正好是最小生成树边数的情况,如果边不够,就把多余点连到中心点上,权值为n,如果m>n-1那么多一条边,答案就减2,可以打表发现,也可以自己理解(因为本来相连是2的,现在变成1了,一来一回就减少了2)。

如果m>=(n-1)*n/2那么答案就是一张边全为1的完全图。


重点!因为权值为n的边是可以任意连的,是没有数量限制的,所以如果边不够的话,多余的点不应该是只用权值为n的边连到中心点的,应该是往其余每个点上都连一条权值为n的边。。。这就是为什么我不够贪心的原因,真的是太蠢了我。。。


#include<iostream>using namespace std;long long n,m;int main(){    long long t;    cin>>t;    while(t--)    {        cin>>n>>m;        if(n==1)        {            cout<<"0"<<endl;            continue;        }        if(m>=(n-1)*n/2)        {            long long ans=n*(n-1);            cout<<ans<<endl;        }        else if(m>n-1)        {            long long  ans=2*n*(n-1);            ans=ans-2*m;            cout<<ans<<endl;        }        else if(m<=n-1)        {            long long y=n-m-1;            long long ans1=y*n*(n-1)+(n-y)*y*n;            long long ans2=m+m+2*m*(m-1);            long long ans=ans1+ans2;            cout<<ans<<endl;        }    }    return 0;}


原创粉丝点击