2017多校训练Contest5: 1006 Rikka with Graph hdu6090

本文介绍了一种算法,用于解决如何构建一个具有最小权重的无向图的问题。该图包含n个节点和不超过m条边,通过精心选择连接哪些节点来最小化所有节点对之间的最短路径总和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


考虑直接以一个点为中心练成一个放射状的图

多出来的边再把发散出来的点两两连线

维护下每种情况的贡献即可

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100001];
int main()
{
    int T;
    scanf("%d",&T);
    while(T>0)
    {
        T--;
        long long n,m;
        scanf("%I64d%I64d",&n,&m);
        if(m>=n*(n-1LL)/2LL)
        {
            printf("%I64d\n",n*(n-1LL));
            continue;
        }
        long long ans=(n-1LL)*n*n;
        long long i;
        if(m<=n-1LL)
        {
            long long d=0;
            for(i=1;i<=m;i++)
            {
                ans-=2LL*((n-1LL)+d*(n-2LL));
                d++;
            }
        }
        else
        {
            long long d=0;
            for(i=1;i<=n-1LL;i++)
            {
                ans-=2LL*((n-1LL)+d*(n-2LL));
                d++;
            }
            m-=(n-1LL);
            ans-=2LL*m;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值