【bzoj 2395】: [Balkan 2011]Timeismoney


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


最小乘積生成樹、、、?

好nb的樣紙啊

感覺和分數規劃的推導差不多。。。。。

複雜度是隨機數據下期望。。。。




#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
////////////////////////////////////////////////
const int N=202;
const int M=10002;
int n,m;
struct edge{int u,v;LL x,y,w;}e[M];
struct Point{
    int x,y;
    Point(){}
    Point(int x,int y):x(x),y(y){}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    LL operator^(const Point &b)const{return x*b.y-y*b.x;}
}ans;
int fa[N];
////////////////////////////////////////////////
bool cmp(edge A,edge B){return A.w<B.w;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
bool unio(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx==fy) return 0;
	return fa[fx]=fy,1;
}
Point kruscal()
{
	Point res=Point(0,0);
	sort(&e[1],&e[m+1],cmp);
	rep(i,0,n-1) fa[i]=i;
	int blk=n;
	rep(i,1,m)
	{
		if(unio(e[i].u,e[i].v))
		{
			res.x+=e[i].x;
			res.y+=e[i].y;
			if(--blk==1) break;
		}
	}
	if(res.x*res.y < ans.x*ans.y || res.x*res.y == ans.x*ans.y && res.x<ans.x) ans=res;
	return res;
}
void cal(Point A,Point B)
{
	rep(i,1,m) e[i].w=e[i].y*(B.x-A.x) + e[i].x*(A.y-B.y);
	Point C=kruscal();
	if((A-C^B-C)>=0) return;
	cal(A,C); cal(C,B);
}
////////////////////////////////////////////////
void input()
{
    n=read(); m=read();
    rep(i,1,m) e[i]=(edge){read(),read(),read(),read()};
}
void solve()
{
	Point A,B;
	ans.x=ans.y=0x3f3f3f3f;
	
	rep(i,1,m) e[i].w=e[i].x;
	A=kruscal();
	
	rep(i,1,m) e[i].w=e[i].y;
	B=kruscal();
	
	cal(A,B);
	printf("%d %d\n",ans.x,ans.y);
}
////////////////////////////////////////////////
int main()
{
    //freopen("_.in","r",stdin); freopen("_.out","w",stdout);
    input(),solve();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章