【BZOJ】【P2395】【Balkan 2011】【Timeismoney】【题解】【最小乘积生成树】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2395

其实还不太会写……

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
struct edge{
	int u,v,w,c,t;
	bool operator<(const edge &E)const{
		return w<E.w;
	}
};
struct Point{
	int x,y;
}ans=(Point){1e9,1e9};
Point minc,mint;
edge edges[10010];
int fa[201];
int find(int x){
	return fa[x]!=x?fa[x]=find(fa[x]):x;
}
int n,m;
Point Mst(){
	Point p=(Point){0,0};
	sort(edges+1,edges+1+m);
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int fx=find(edges[i].u),fy=find(edges[i].v);
		if(fx!=fy){
			fa[fx]=fy;
			p.x+=edges[i].c;
			p.y+=edges[i].t;
		}
	}
	if((LL)ans.x*ans.y==(LL)p.x*p.y&&ans.x>p.x)ans=p;
	if((LL)ans.x*ans.y>(LL)p.x*p.y)ans=p;
	return p;
}
LL Cross(Point x,Point y,Point z)
{
	return((LL)(x.x-z.x)*(y.y-z.y)-(LL)(x.y-z.y)*(y.x-z.x));
}
void solve(Point minc,Point mint)
{
	LL c=mint.x-minc.x,t=minc.y-mint.y;
	for (int i=1;i<=m;i++) edges[i].w=edges[i].c*t+edges[i].t*c;
	Point p=Mst();
	if (Cross(p,minc,mint)>=0) return;
	solve(minc,p);
	solve(p,mint);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d%d",&edges[i].u,&edges[i].v,&edges[i].c,&edges[i].t),
		edges[i].u++,edges[i].v++;
	for(int i=1;i<=m;i++)edges[i].w=edges[i].c;
	minc=Mst();
	for(int i=1;i<=m;i++)edges[i].w=edges[i].t;
	mint=Mst();
	solve(minc,mint);
	printf("%d %d\n",ans.x,ans.y);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值