现在的位置: 首页 > 综合 > 正文

[Balkan 2011]Timeismoney

2014年03月03日 ⁄ 综合 ⁄ 共 1738字 ⁄ 字号 评论关闭

bzoj2395

每条边有两个权值,c[i],t[i],求一棵生成树使sigma(c[i])*sigma(t[i])最小

ž设Sigma(a)*sigma(b)=k
ž则sigma(b)=k/sigma(a),是个反比例函数,求出y坐标最小的和x坐标最小的,则将两个点连线,之上的点肯定不优,接着用此线去切(以此斜率类似最优比率生成树去判定,此处最好不用实数,很慢很慢),切点是最优解的候选解,再递归去连线(三角形内部点肯定不优)
ž直到新的点在两点直线上。

最后两个点卡常数啊,我调了很久,double不能用,要改为B*C[I]+A*T[I]。原理大约是用凸壳,但是为什么求出斜率后再求mst就不知道了。

次小乘积生成树

žWc众神犇也没yy出来。
ž大概有两种思路。
ž第一种在次小凸壳(每次选次小点)找最小点并在最小凸壳找次小点(正确性完全木有证明)
ž第二种不记得了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
struct line
{
  int i;int w;
}a[10050],p,q;
const int maxn=210;
int fa[maxn],n,m,l[10050],r[10050];
int c[10050],t[10050],anc,ant,ans;
double pd;
int find(int x) {if (fa[x]!=x) fa[x]=find(fa[x]);return fa[x];}
void updata(int cc,int tt) {if (cc*tt<ans) ans=cc*tt,anc=cc,ant=tt;}
int cmp1(const void *i,const void *j) 
{
  p=*(line *)i,q=*(line *)j;
  pd=p.w-q.w;
  if (pd>0) return 1;else return -1;
}
void kruskal(int &cc,int &tt)
{
  int i,j,ll,rr;
  qsort(a+1,m,sizeof(a[1]),cmp1);
  for (i=1;i<=n;i++) fa[i]=i;
  for (i=1;i<=m;i++)
  {
    ll=find(fa[l[a[i].i]]),rr=find(fa[r[a[i].i]]);
    if (ll!=rr) fa[rr]=ll,cc+=c[a[i].i],tt+=t[a[i].i];
  }
}
int cmp(int px,int py,int qx,int qy) {return (px*qy-py*qx);}
void dfs(int ac,int at,int bc,int bt)
{
  int cc=0,tt=0;
  int A=bc-ac,B=at-bt;
  for (int i=1;i<=m;i++)  a[i].w=B*c[a[i].i]+A*t[a[i].i];
  kruskal(cc,tt);
  if (cmp(ac-bc,at-bt,cc-bc,tt-bt)<=0) {updata(ac,at),updata(bc,bt);return ;}
  dfs(ac,at,cc,tt),dfs(cc,tt,bc,bt);
}
void init()
{
  int i,x,y;
  int ac=0,at=0,bc=0,bt=0;
  scanf("%d%d\n",&n,&m);
  for (i=1;i<=m;i++) scanf("%d%d%d%d\n",&x,&y,&c[i],&t[i]),x++,y++,l[i]=x,r[i]=y;
  ans=1073741819,anc=0,ant=0;
  for (i=1;i<=m;i++)  a[i].w=c[i],a[i].i=i;
  kruskal(ac,at);updata(ac,at);
  for (i=1;i<=m;i++)  a[i].w=t[a[i].i];
  kruskal(bc,bt);updata(bc,bt);  
  if ((ac!=bc)||(at!=bt)) dfs(ac,at,bc,bt);
  printf("%d %d\n",anc,ant);
}
int main()
{
  freopen("timeismoney.in","r",stdin);
  freopen("timeismoney.out","w",stdout);
    init();
  return 0;
}

抱歉!评论已关闭.