BZOJ 2395 Time is Money
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2395
直接上题解:http://www.cnblogs.com/autsky-jadek/p/3959446.html
很好看懂,感受到了画图的力量!点对投射到二维空间中去,感觉就会明了很多的样子...
不过复杂度什么的...虽然不能直接算出来,不过跑得很快。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=210; const int maxm=10010; struct Edge{ int u,v,w,t,c; }e[maxm]; struct Point{ int x,y; Point(){x=0,y=0;} Point(int a,int b){x=a,y=b;} }ans; typedef Point Vector; typedef long long ll; Vector operator - (const Point &A,const Point &B){ return Vector(A.x-B.x,A.y-B.y); } ll Cross(const Vector &A,const Vector &B){ return (ll)A.x*B.y-(ll)A.y*B.x; } bool cmp(const Edge &A,const Edge &B){ return A.w<B.w; } int n,m; int p[maxn]; int Find(int x){ int r=x,pre; while(p[r]!=r) r=p[r]; while(x!=r) pre=p[x],p[x]=r,x=pre; return x; } Point Kruscal(){ Point res; int cot=1,fx,fy; for(int i=1;i<=n;i++) p[i]=i; for(int i=1;i<=m && cot<n;i++){ fx=Find(e[i].u),fy=Find(e[i].v); if(fx!=fy) cot++,res.x+=e[i].c,res.y+=e[i].t,p[fx]=fy; } if((ll)ans.x*ans.y>(ll)res.x*res.y || ((ll)ans.x*ans.y==(ll)res.x*res.y && ans.x>res.x)) ans=res; return res; } void Div(Point A,Point B){ for(int i=1;i<=m;i++) e[i].w=e[i].c*(A.y-B.y)+e[i].t*(B.x-A.x); sort(e+1,e+m+1,cmp); Point C=Kruscal(); if(Cross(B-A,C-A)>=0) return ; Div(A,C);Div(C,B); } int main(){ #ifndef ONLINE_JUDGE freopen("2395.in","r",stdin); freopen("2395.out","w",stdout); #endif Point A,B; ans.x=1e9,ans.y=1e9; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].c,&e[i].t); e[i].u++,e[i].v++; } for(int i=1;i<=m;i++) e[i].w=e[i].c; sort(e+1,e+m+1,cmp); A=Kruscal(); for(int i=1;i<=m;i++) e[i].w=e[i].t; sort(e+1,e+m+1,cmp); B=Kruscal(); Div(A,B); printf("%d %d",ans.x,ans.y); return 0; }