很久以前,whalyzh同学去沙漠旅行,看到了很多很多的仙人掌,
但是现在whalyzh同学已经想不起来最酷炫的那棵仙人掌长什么样了,只记得一些特征。
小Q同学根据whalyzh同学的描述,发现这棵仙人掌可以画成一个无向的连通图,这个图不存在自环,且任意一条边至多属于一个简单环。所谓简单环,是指在图中任取一个顶点作为起点,沿着不重复的边、经过不重复的点再次走到起点的闭合路径。定义一棵仙人掌的酷炫程度为这棵仙人掌对应的图中简单环的长度最大值乘以简单环的长度最小值,如果没有环,则酷炫程度为0。
现在whalyzh同学还记得这棵仙人掌的顶点数和边数,你需要所有满足条件的仙人掌的酷炫程度的最大值。
第一行是一个正整数,表示测试数据的组数,
每组测试数据只有一行,包含两个整数,表示仙人掌的顶点数和边数。
对于每组测试数据,输出一个整数,表示仙人掌的酷炫程度的最大值,如果不存在满足条件的仙人掌,请输出-1。
4 2 0 2 1 2 2 2 3
-1 0 4 -1
对于第二组样例,满足条件的仙人掌只有一种,且无环,故酷炫程度的最大值为0。
对于第三组样例,满足条件的仙人掌只有一种,且只有一个长为2的简单环,故酷炫程度的最大值为4。
无向连通无自环且每一边至多属于一个简单环(‘至多‘说明可以不在环上)的图叫仙人掌,定义一棵仙人掌的酷炫程度为这棵仙人掌对应的图中简单环的长度最大值乘以简单环的长度最小值,如果没有环,则酷炫程度为0。
仙人掌的顶点数n和边数m,求满足条件的仙人掌的酷炫程度的最大值
解题思路:
分为几种情况:
m小于n-1则无法连通,不能算是仙人掌,输出-1。
m==n-1恰好是一棵树,但是没有简单环,输出0,
m==n 可以形成一个环,长度为n,既为最大也为最小,输出n*n
之后考虑m>n时的仙人掌,最优解的图中所有边一定都是在某个环上的,因为如果不是的话,可以把这条边加到环里,仍然是仙人掌,答案会更优。同时考虑到图中环的个数,加一个边就会多一个环(构造试出来可以),所以环的个数为m-n+1,发现加边加到2*n-2就没法再加了(变成菊花图)所以m>2*n-2输出-1.,
然后环数有了,边数m有了,就把边分配给每个环,可以证明有最优解里除了最大环剩下的环的长度是一样的,因为如果有不一样的可以添加到最大环上答案更优,所以设最小环长度为x,f(x)=x*(m-(m-n+1-1)x) (x>=2&&x<=m/(m-n+1)) 要求的就是f(x)max,找到对称轴,带进去算即可,注意对称轴两侧的整数都可能是解。
#include<cstdio> #include<algorithm> #define ll long long using namespace std; ll n, m; int main() { int t; scanf("%d",&t); while(t--) { scanf("%lld %lld", &n, &m); if (m < n - 1 || m>2 * n - 2)printf("-1\n"); else if (m == n - 1)printf("0\n"); else if (m == n)printf("%lld\n", 1ll*n*n); else { ll p = m / (2 * (m - n)),tem=0;//别忘初始化,之后的那个if不一定会进去 if (p > 1&&p<= m/(m-n))tem = p*m - (m - n)*p*p;//? p++; if (p<=m/(m-n))tem = max(tem, p*m-(m - n)*p*p); printf("%lld\n", tem); } } }