http://acm.split.hdu.edu.cn/showproblem.php?pid=6090
Rikka with Graph
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 25 Accepted Submission(s): 17
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=1∑nj=1dist(i,j) .
Now, Yuta has n nodes, and he wants to choose no more than m pairs of nodes (i,j)(i≠j) 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) .
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=1∑nj=1dist(i,j) .
Now, Yuta has n nodes, and he wants to choose no more than m pairs of nodes (i,j)(i≠j) 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(1≤t≤10)
, the number of the testcases.
For each testcase, the first line contains two numbers n,m(1≤n≤106,1≤m≤1012) .
For each testcase, the first line contains two numbers n,m(1≤n≤106,1≤m≤1012) .
Output
For each testcase, print a single line with a single number -- the answer.
Sample Input
1 4 5
Sample Output
14
Source
题意:有n个点,你可以填上m条边。连通的两点间的距离就是最短路上的边数,不连通的话是n。求出填上边后的距离之和的最小值。
题解:多写几组之后发现,最优的填法是:选定一个点,先把该点与其他所有点连满,若有多的边,再选下一个点与其他点连满(这或许是一个结论,但是图论学的不精)。计算的时候我是用全部不连的状态减去每次连边后两点间的距离减少的值,具体看代码理解。
代码:
#include<bits/stdc++.h>
#define debug cout<<"aaa"<<endl
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;
const int N = 100000 + 5;
const int mod = 1000000000 + 7;
int main(){
int t;
LL n,m,ans;
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&n,&m);
ans=n*n*(n-1);
if(m<=n-1){
//减去减少的距离,这个形成的是一颗树:有m个叶子节点,都连在根节点上,其余的都是孤立点距离不变
ans=ans-m*(m-1)*(n-2)-2*m*(n-1);
}
else if(m>n*(n-1)/2){
//全部连上的情况,直接计算结果
ans=n*(n-1);
}
else{
//连上n-1条边后就是一颗树:有n-1个叶子节点,都连在根节点上
//在这棵树上再添加边,那么这条边上的两点的距离就从原来的2,变成了1
ans=ans-2*(n-1)*(n-1)-2*(m-n+1)-(n-1)*(n-2)*(n-2);
}
printf("%lld\n",ans);
}
return 0;
}