hdu6090 Rikka with Graph (找规律)

题目:

给n个点,可以在任意两个点之间建立边,每条边的值都是1。允许添加不超过m条边,问 ni=1 nj=1 dist(i,j)的最小值是多少。若i,j无法连通,则规定dist(i,j)=n,否则等于最短路的长度。

分析:

这道题在比赛的时候没有做出来,能看出来是找规律推公式。当时直接试图找出一种令距离最短的构造边的方式,先围一个圈,然后再把所有相隔一个点的点连起来,再然后是相隔两个,以此类推。可发现这样计算不太会继续距离,便放弃了这个想法。队友提供了一种思路,先满足局部最优,即令m条边先满足k个点是最优状态,然后如果有剩的边再加进去,没有就直接算距离。可后来发现加进去剩余的边也出了问题,这样貌似不能构造出最优解。于是这道题至此彻底做不出。

其实比赛过程中离正确答案很近过。若现在边数大于等于最优状态时的边数,那么任意两个点之间的距离都是1。(下面分析的思路是重点)此时,如果在“完美”的基础上每少一条边,那么总距离就会增加 2 。直到m = n - 1 ,此时一个点在中间,和剩下点直接相连。在此之前,所有点都可通过中间这个点以最大距离不超过2的代价到达任意一点,所以每去一条边总距离加2。在此之后,每去一条边,就会有一个孤立的点。重新算距离即可。

应该反思自己的思考能力。要有逻辑性。

代码:

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const double EPS=1e-8;
const int INF=0x3f3f3f3f;
ll n,m;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        ll ans = 0;
        if(m >= n*(n-1)/2){
            ans = n*(n-1);
        }else if(m >= n-1){
            ans = n*(n-1) + 2*(n*(n-1)/2-m); 
        }else{
            ans = m+n*(n-m-1) + m*(1+2*(m-1)+n*(n-m-1)) + (n-m-1)*n*(n-1);
        }
        printf("%lld\n",ans);
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值