分析:其实是个数学题。。首先将已经匹配的m对连好,然后在不增加增广路的基础上尽量多地加边。对于二分图,增广路就是某条路径,第1、3、5、...、条边没有被连,第2、4、6...条边被连,且最后一条是被连的。然后将点分为4类:左边没有被匹配的为d1,左边与右边没有被匹配的点之间有通路的点为a1,左边与左边没有被匹配的点之间有通路的点为b1,左边没有与没有被匹配的点之间有通路的为c1,右边的同理设为a2、b2、c2、d2(- - 有点绕。。画个图就好理解了。。)。然后很容易可以得出结论:d1=n-m1,d2=n-m2,c1=c2,b1=a2,b2=a1,设a=a1,b=b1,c=c1,则a+b+c=m,并且由分类的定义和贪心可得,最终答案为ans=a^2+b^2+c^2+a*(n2-m)+b*(n1-m)+a*b。每个点至少连d条边,即c=0或c>=d,a>=d,b>=d,然后代到ans中讨论,又ans的单调性得到只有三种情况下可能取得最值,即(a,b,c)=(d,d,m-2*d),(m-2*d,d,d),(m-d,d,0),然后比较下谁大,注意检查无解情况即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 typedef long long ll; 7 ll n1,n2,m,d; 8 ll f(ll a,ll b,ll c){return a*a+b*b+c*c+a*(n2-m)+b*(n1-m)+a*b;} 9 int main(){ 10 // freopen("e:\\in.txt","r",stdin); 11 int T; 12 scanf("%d",&T); 13 while(T--){ 14 ll ans; 15 int k1=2,k2=2; 16 scanf("%lld%lld%lld%lld",&n1,&n2,&m,&d); 17 ll a1[3]={0,n1/2,m},a2[3]={0,n2/2,m}; 18 if(n1==m||n2==m){ 19 printf("%lld\n",n1*n2);continue; 20 } 21 if(m>n1||m>n2||m-d<d){ 22 printf("-1\n");continue; 23 } 24 if(n1>n2){ll t=n1;n1=n2;n2=t;} 25 ans=f(m-d,d,0); 26 if(m-2*d>=0){ 27 ans=max(ans,f(d,d,m-2*d)); 28 ans=max(ans,f(m-2*d,d,d)); 29 } 30 printf("%lld\n",ans); 31 } 32 return 0; 33 }
时间: 2024-10-20 19:17:29