hdu 6090(二)

Rikka with Graph

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 72    Accepted Submission(s): 51



Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

For an undirected graph G with n nodes and m edges, we can define the distance between (i,j) ( dist(i,j) ) as the length of the shortest path between i and j . The length of a path is equal to the number of the edges on it. Specially, if there are no path between i and j , we make dist(i,j) equal to n .

Then, we can define the weight of the graph G ( wG ) as ni=1nj=1dist(i,j) .

Now, Yuta has n nodes, and he wants to choose no more than m pairs of nodes (i,j)(ij) and then link edges between each pair. In this way, he can get an undirected graph G with n nodes and no more than m edges.

Yuta wants to know the minimal value of wG .

It is too difficult for Rikka. Can you help her?  

In the sample, Yuta can choose (1,2),(1,4),(2,4),(2,3),(3,4) .
 

Input
The first line contains a number t(1t10) , the number of the testcases.

For each testcase, the first line contains two numbers n,m(1n106,1m1012) .
 

Output
For each testcase, print a single line with a single number -- the answer.
 

Sample Input
  
  
1 4 5
 

Sample Output
  
  
14
 

题目大意:给你两个数字n,m分别代表的是有多少点多少边,每个边的长度为1,现在让你求m条边构成的图中,所有的点相连所需要的长度和最小。

解题思路:找规律,发现m在不同的范围内,所求的答案有不同的公式表示,每两个点之间共有n*(n-1)/2种可能如果m大于等于这个数就直接为n*(n-1)如果少于它则一个边一个边的进行拆除没拆一个边就增加2然后到一个临界点为m=n-1一个点分别连其他的点可以根据上一个算出,当m小于这个数的时候就分为孤立的点了,有一部分相连,就和上一种情况一样然后分联通的,孤立的,联通的与孤立的分别计算。

  1. #include<cstdio>  
  2. using namespace std;  
  3. int main()  
  4. {  
  5.     int t;  
  6.     scanf("%d",&t);  
  7.     while(t--)  
  8.     {  
  9.         long long n,m,p,q;  
  10.         scanf("%lld%lld",&n,&m);  
  11.         long long ans=0;  
  12.         int flag=0;  
  13.         if(m>n*(n-1)/2)///在这个范围内代表每两个点之间都可以一步连到所以为n*(n-1)  
  14.         {  
  15.             printf("%lld\n",n*(n-1));  
  16.             flag=1;  
  17.         }  
  18.         else if(m>=n-1&&m<=n*(n-1)/2)///在这个范围内与m为n*(n-1)/2相比每少一条边就减少2  
  19.       {  
  20.             ans+=((n*(n-1)/2)-m)*2+n*(n-1);  
  21.         }  
  22.         else///这个范围内分为孤立的点与连在一起的点,分三块计算  
  23.         {  
  24.             p=m+1;  
  25.             q=n-m-1;  
  26.             ans+=q*p*n*2+q*(q-1)*n+(p-1)*(p-1)*2;  
  27.         }  
  28.         if(flag==0)  
  29.         printf("%lld\n",ans);  
  30.     }  
  31. }  
#include<cstdio>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long n,m,p,q;
        scanf("%lld%lld",&n,&m);
        long long ans=0;
        int flag=0;
        if(m>n*(n-1)/2)///在这个范围内代表每两个点之间都可以一步连到所以为n*(n-1)
        {
            printf("%lld\n",n*(n-1));
            flag=1;
        }
        else if(m>=n-1&&m<=n*(n-1)/2)///在这个范围内与m为n*(n-1)/2相比每少一条边就减少2
      {
            ans+=((n*(n-1)/2)-m)*2+n*(n-1);
        }
        else///这个范围内分为孤立的点与连在一起的点,分三块计算
        {
            p=m+1;
            q=n-m-1;
            ans+=q*p*n*2+q*(q-1)*n+(p-1)*(p-1)*2;
        }
        if(flag==0)
        printf("%lld\n",ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值