51nod 1397 最大二分图(图论+思维)

分析:其实是个数学题。。首先将已经匹配的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
",n1*n2);continue;
20         }
21         if(m>n1||m>n2||m-d<d){
22             printf("-1
");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
",ans);
31     }
32     return 0;
33 }
原文地址:https://www.cnblogs.com/7391-KID/p/7587672.html