给你n个点,让你连m条边,使得任意两两点对之间的最短路的和最小(两点若不可达,最短路记作n)。
初始时ans=n*n*(n-1)。
先尽量连成菊花图,每连一次让答案减小2*((n-2)*(i-1)+(n-1)),i为当前菊花图中的点数。
连完后剩下的边,每连一次让答案减小2。
如果已经用了n*(n-1)/2条边,剩下的边没有意义。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; ll ans,m; int T,n; int main(){ scanf("%d",&T); for(;T;--T){ scanf("%d%lld",&n,&m); ans=(ll)n*(ll)(n-1)*(ll)n; if(m<(ll)n){ for(int i=1;i<=(int)m;++i){ ans-=(ll)(i-1)*(ll)(n-2)*2ll; ans-=(ll)(n-1)*2ll; } } else{ for(int i=1;i<n;++i){ ans-=(ll)(i-1)*(ll)(n-2)*2ll; ans-=(ll)(n-1)*2ll; } ll lim=min((ll)n*(ll)(n-1)/2ll,m); ans-=(lim-(ll)n+1ll)*2ll; } printf("%lld ",ans); } return 0; }