bzoj2395: [Balkan 2011]Timeismoney

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

思路:与bzoj3571类似的思想,只是内部是kruskal而已

其实数据范围最大是会爆int的,然而并没有爆

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int maxn=210,maxm=10010;
using namespace std;
struct Edge{int x,y,a,b,v;}E[maxm];
struct poi{int x,y;}L,R,ans;
bool operator <(Edge a,Edge b){return a.v<b.v;}
poi operator -(poi a,poi b){return (poi){a.x-b.x,a.y-b.y};}
int operator *(poi a,poi b){return a.x*b.y-a.y*b.x;}
bool operator <(poi a,poi b){
	int va=a.x*a.y,vb=b.x*b.y;
	return va!=vb?va<vb:a.x<b.x;
}
bool operator ==(poi a,poi b){return a.x==b.x&&a.y==b.y;}
poi min(poi a,poi b){return a<b?a:b;}
int n,m,fa[maxn];
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
poi kruskal(){
	for (int i=1;i<=n;i++) fa[i]=i;
	sort(E+1,E+1+m);poi res=(poi){0,0};
	for (int i=1;i<=m;i++){
		int x=E[i].x,y=E[i].y;
		if (getfa(x)!=getfa(y)) fa[getfa(x)]=getfa(y),res.x+=E[i].a,res.y+=E[i].b;
	}
	ans=min(ans,res);
	return res;
}

void solve(poi l,poi r){
	for (int i=1;i<=m;i++) E[i].v=(l.y-r.y)*E[i].a+(r.x-l.x)*E[i].b;
	poi mid=kruskal();//printf("l%d %d mid%d %d r%d %d\n",l.x,l.y,mid.x,mid.y,r.x,r.y);
	if ((r-l)*(mid-l)<0) solve(l,mid),solve(mid,r);
}

int main(){
	scanf("%d%d",&n,&m);ans=(poi){30000,30000};
	for (int i=1;i<=m;i++) scanf("%d%d%d%d",&E[i].x,&E[i].y,&E[i].a,&E[i].b),E[i].x++,E[i].y++;
	for (int i=1;i<=m;i++) E[i].v=E[i].a;L=kruskal();
	for (int i=1;i<=m;i++) E[i].v=E[i].b;R=kruskal();
	solve(L,R),printf("%d %d\n",ans.x,ans.y);
	return 0;
}


posted @ 2016-01-11 20:32  orzpps  阅读(194)  评论(0编辑  收藏  举报