zoukankan      html  css  js  c++  java
  • BZOJ 2395 Timeismoney

    最小乘积生成树。

    本质上是把生成树作为平面上的点,那么答案一定在下凸壳上。

    递归求解。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxv 250
    #define maxe 10050
    #define inf 1000000007
    using namespace std;
    int n,m,a,b,c,d,father[maxv];
    struct edge
    {
        int x,y,a,b,c;
        edge (int x,int y,int a,int b):x(x),y(y),a(a),b(b) {}
        edge () {}
    }e[maxe];
    struct point
    {
        int a,b;
        point (int a,int b):a(a),b(b) {}
        point () {}
        friend point operator - (const point & x,const point & y)
        {
            return point(x.a-y.a,x.b-y.b);
        }
        friend int operator * (const point & x,const point & y)
        {
            return x.a*y.b-x.b*y.a;
        }
        friend bool operator < (const point &x,const point & y)
        {
            long long ans1=(long long)x.a*x.b,ans2=(long long)y.a*y.b;
            return ans1==ans2?x.a<y.a:ans1<ans2;
        }
    }ans;
    bool cmp1(const edge & x,const edge & y)
    {
        if (x.a!=y.a) return x.a<y.a;
        return x.b<y.b;
    }
    bool cmp2(const edge & x,const edge & y)
    {
        if (x.b!=y.b) return x.b<y.b;
        return x.a<y.a;
    }
    bool cmp3(const edge & x,const edge & y)
    {
        if (x.c!=y.c) return x.c<y.c;
        else if (x.a!=y.a) return x.a<y.a;
        else return x.b<y.b;
    }
    int getfather(int x)
    {
        if (x!=father[x]) father[x]=getfather(father[x]);
        return father[x];
    }
    point kruskal()
    {
        point ret=point(0,0);
        for (int i=1;i<=n;i++) father[i]=i;
        for (int i=1;i<=m;i++)
        {
            int x=e[i].x,y=e[i].y;
            int f1=getfather(x),f2=getfather(y);
            if (f1!=f2) {father[f1]=f2;ret.a+=e[i].a;ret.b+=e[i].b;}
        }
        if (ret<ans) ans=ret;
        return ret;
    }
    void min_product_tree(point A,point B)
    {
        point C;
        for (int i=1;i<=m;i++) e[i].c=(A.b-B.b)*e[i].a+(B.a-A.a)*e[i].b;
        sort(e+1,e+m+1,cmp3);C=kruskal();
        if ((A-B)*(C-B)<=0) return;
        min_product_tree(A,C);min_product_tree(C,B);
    }
    int main()
    {
        ans=point(inf,inf);
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);a++;b++;
            e[i]=edge(a,b,c,d);
        }
        point A,B,C;
        sort(e+1,e+m+1,cmp1);A=kruskal();
        sort(e+1,e+m+1,cmp2);B=kruskal();
        min_product_tree(A,B); 
        printf("%d %d
    ",ans.a,ans.b);
        return 0;
    }
  • 相关阅读:
    [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例
    玩转Asp.net MVC 的八个扩展点
    float实例讲解
    C#高性能TCP服务的多种实现方式
    如何把SQLServer数据库从高版本降级到低版本?
    ASP.NET MVC Area使用-将Area设置成独立项目
    如何使用ping和tracert命令测试网站访问速度
    ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)
    MVC Action Filter
    c#中单元测试
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6337966.html
Copyright © 2011-2022 走看看