题意
要你求最小乘积生成树
题解
最小乘积生成树的裸题啊
题解
在随机数据下,凸包点数是
logn−−−−√
l
o
g
n
的
因此会跑得很快
CODE:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const LL N=205;
const LL M=10005;
LL n,m;
struct qq
{
LL x,y,t,c,v;//连接的两个电 x坐标 y坐标 拿来比较的东西
}e[M];
struct node
{
LL x,y;
}ans;
bool cmp (qq x,qq y){return x.v<y.v;}
LL f[N];
LL find (LL x){return f[x]==x?f[x]:f[x]=find(f[x]);}
node update ()
{
sort(e+1,e+1+m,cmp);
for (LL u=1;u<=n;u++) f[u]=u;
node p;p.x=0;p.y=0;
LL now=0;
for (LL u=1;u<=m;u++)
{
LL x=find(e[u].x),y=find(e[u].y);
if (x==y) continue;
f[x]=y;
p.x=p.x+e[u].c;p.y=p.y+e[u].t;
now++;
if (now>=n-1) break;
}
if ((ans.x*ans.y>p.x*p.y)||(ans.x*ans.y==p.x*p.y&&p.x<ans.x)) ans=p;
return p;
}
LL mul (node x,node y,node z)
{
LL x1=x.x-z.x,y1=x.y-z.y;
LL x2=y.x-z.x,y2=y.y-z.y;
return x1*y2-x2*y1;
}
void solve (node x,node y)
{
LL yy=x.y-y.y,xx=y.x-x.x;
for (LL u=1;u<=m;u++) e[u].v=e[u].c*yy+e[u].t*xx;
node p=update();
if (mul(p,x,y)>=0) return ;
//if (Cross(p,x,y)>=0) return;
solve(x,p);solve(p,y);
}
int main()
{
scanf("%lld%lld",&n,&m);
for (LL u=1;u<=m;u++)
{
scanf("%lld%lld%lld%lld",&e[u].x,&e[u].y,&e[u].c,&e[u].t);
e[u].x++;e[u].y++;
}
ans.x=1e9;ans.y=1e9;
for (LL u=1;u<=m;u++) e[u].v=e[u].c;
node a=update();
for (LL u=1;u<=m;u++) e[u].v=e[u].t;
node b=update();
// printf("%lld %lld\n",ans.x,ans.y);
solve(a,b);
printf("%lld %lld\n",ans.x,ans.y);
return 0;
}