30分做法:n^4枚举边.
100分做法: 枚举每一条边,设两个端点为x,y; 我们通过组合公式来计算 Y 的个数,每一次加上C(num[x]-1)*(num[y]-1); 通过记连接一个点的边的最大值,次大值,第三大值。 加上除去枚举的边外x连接的最大的两条边,以及y连接的除去… 之后最大的边。 然后再将x和y换过来,重复一遍。重复上述操作。
#include#include #include #include #include #include #define LL long longusing namespace std;int n;LL maxn,ans;struct H{ LL m1,m2,m3; int t1,t2,t3;}a[200009];//点 struct HH{ LL x,y,l;}b[200009];//边 LL cnt,num[200009];void ex(int x,int y,int z){ if(z>=a[x].m1) { a[x].m3=a[x].m2; a[x].m2=a[x].m1; a[x].m1=z; a[x].t3=a[x].t2; a[x].t2=a[x].t1; a[x].t1=y; } else if(z>=a[x].m2) { a[x].t3=a[x].t2; a[x].t2=y; a[x].m3=a[x].m2; a[x].m2=z; } else if(z>a[x].m3) { a[x].t3=y; a[x].m3=z; }}LL C(LL x)//从x个中任选2个 !一定要开LL { return x*(x-1)/2;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ a[i].m1=a[i].m2=a[i].m3=0; a[i].t1=a[i].t2=a[i].t3=i; } for(int i=1;i =3&&num[y]>=2) { LL p=0; if(a[x].t1==y) p=a[x].m2+a[x].m3; else if(a[x].t2==y) p=a[x].m1+a[x].m3; else p=a[x].m1+a[x].m2; if(a[y].t1==x) p+=a[y].m2; else p+=a[y].m1; p+=len; maxn=max(p,maxn); ans+=C(num[x]-1)*(num[y]-1); } int tmp=x;x=y,y=tmp; if(num[x]>=3&&num[y]>=2) { LL p=0; if(a[x].t1==y) p=a[x].m2+a[x].m3; else if(a[x].t2==y) p=a[x].m1+a[x].m3; else p=a[x].m1+a[x].m2; if(a[y].t1==x) p+=a[y].m2; else p+=a[y].m1; p+=len; maxn=max(p,maxn); ans+=C(num[x]-1)*(num[y]-1); } } printf("%lld\n%lld",ans,maxn); return 0;}