标签:距离 src turn wan training ios mat 节点 task
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
题意:有n各点,问取其中至多m对点连成边,每条边的权值为1,求连好之后所有点之间的最短路(记为dis(i,j))的和的最小值。若两个点不是连通的,则这两条边的dis取作n。
思路:贪心。
1.当m<=n-1时,我们尽可能每一条边都把不同的点连通,我们可以把 ① 点作为根节点,每加入一条边,就从这个根节点连接到另一个不在连通块里的点(见下图,虚线代表下一条连接的边)。
对于被连接的点来说,它到根节点的距离从 n -> 1, 到其他在子节点的距离从 n -> 2, 所以加入第 i 个点后,原先总距离之和减少了 2*[(n-1)+(i-1)*(n-2)]。由于m=0(即没有边)时总距离和为 n*n*(n-1), 此时总距离和为
2.当m>n-1时,剩余的点两两相连,由于每两个子节点之间距离都是2,每连一条边都只有一对点的距离从2变为1,所以每多连一条边,总距离减少 2*1,所以在上式的基础上减去 2*(m-(n-1)) 即可。注意当m > n*(n-1)/2时最多能取n*(n-1)/2对点, res=n*(n-1)。
AC代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; typedef long long LL; int main() { LL n,m; int T; cin>>T; while(T--) { scanf("%lld %lld", &n, &m); LL res=n*n*(n-1); if(m>0){ if(m<=n-1){ res=res-m*(m-1)*(n-2)-2*m*(n-1); } else if(m>n*(n-1)/2) res=n*(n-1); else{ res=res-(n-1)*(n-2)*(n-2)-2*(n-1)*(n-1)-2*(m-n+1); } } printf("%lld\n", res); } return 0; }
HDU 6090 Rikka with Graph —— 2017 Multi-University Training 5
标签:距离 src turn wan training ios mat 节点 task
原文地址:http://www.cnblogs.com/MasterSpark/p/7310227.html