hdu--6090--Rikka with Graph

Rikka with Graph

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


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个点,你可以在这n个点之间任意连<=m条线,使∑ni=1∑nj=1dist(i,j).的值最小。

其中dist(i,j)表示如过i和j之间有通路,则dist(i,j)的值为i和j之间经过的边数。如a--->b---c

(前提是没有a--->c,如过有的话,就取 1 而不是 2 ,因为要使值最小)那么dist(a,c)等于2
因为经过了两条边,如过a和b之间没有通路,那么dist(a,b)就等于n。


解题思路:
很显然,这是一道找规律的题,根据m和n的关系进行分类讨论,
1,   如过m>=n*(n-1)/2;就说明图中任意的两个点之间都有通路,答案可以直接得出,为n*(n-1);
2,  如过n-1<=m      拆除边的数量为n*(n-1)/2)-m,答案要加上的值就为2*(n*(n-1)/2)-m);
3,如过m

     孤立的点分开算,
ps:设孤立的点的个数为q,连通的点的个数为p;


   对于孤立的点:每个点之间的权重为n,这几个孤立的对答案的贡献为q*(q-1)*n;
   对于连通的点:比较容易得出这几个连通的点,对答案的贡献为(p-1)*(p-1)*2;  
   最后再把孤立的点与非孤立的点进行连通,他们之间的权重都为n,对答案的贡献都为q*p*n,所以为2倍的q*p*n;

代码:


 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include
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)
        {
            printf( "%lld\n", n * (n -  1));
            flag =  1;
        }
         else  if(m >= n -  1 && m <= n * (n -  1) /  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);
    }
}




你可能感兴趣的:(算法_杭电多校联合)