# LuoguP5540:【模板】最小乘积生成树（几何逼近）

#include<bits/stdc++.h>
#define ll long long
#define pii pair<ll,ll>
#define f first
#define ss second
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
struct in{
int u,v;ll a,b,C;
}s[maxn];
bool cmp(in p,in q){ return p.C<q.C;}
int fa[maxn],N,M; ll ans=1LL<<60; pii fcy;
int find(int x){
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
pii solve()
{
pii res=make_pair(0,0);
rep(i,1,N) fa[i]=i;
sort(s+1,s+M+1,cmp);
rep(i,1,M) {
if(find(s[i].u)==find(s[i].v)) continue;
fa[find(s[i].u)]=find(s[i].v);
res.f+=s[i].a;
res.ss+=s[i].b;
}
if(res.f*res.ss<ans||(res.f*res.ss==ans&&res.f<fcy.f)) ans=res.f*res.ss,fcy=res;
return res;
}
void MinMul(pii A,pii B)
{
pii C;
rep(i,1,M) s[i].C=(B.f-A.f)*s[i].b+(A.ss-B.ss)*s[i].a;
C=solve();
if(1LL*(B.f-A.f)*(C.ss-A.ss)-1LL*(B.ss-A.ss)*(C.f-A.f)>=0) return ;
MinMul(A,C);
MinMul(C,B);
}
int main()
{
pii A,B;
scanf("%d%d",&N,&M);
rep(i,1,M) {
scanf("%d%d%lld%lld",&s[i].u,&s[i].v,&s[i].a,&s[i].b);
s[i].u++; s[i].v++;
}
rep(i,1,M) s[i].C=s[i].a;
A=solve();
rep(i,1,M) s[i].C=s[i].b;
B=solve();
MinMul(A,B);
printf("%lld %lld\n",fcy.f,fcy.ss);
return 0;
}

It is your time to fight！
posted @ 2019-09-28 09:59  nimphy  阅读(231)  评论(0编辑  收藏  举报