zoukankan      html  css  js  c++  java
  • 「HNOI 2014」 画框

    题目链接

    戳我

    (Solution)

    这一题很像最小乘积生成树.只是把(kruskal)变为了(km)/费用流

    现在来讲一讲最小乘积生成树.首先将(sum a_i)(sum b_i)看为坐标轴上的点((x,y))

    (step 1:) 首先找出离(x)最近的点和离(y)最近的点
    (step 2:) 找出距离(A,B)最远的(C)((C)要在(A,B)左边)
    (step 3:) 递归处理(AC)(CB),直到找不到(C)为止

    现在来讲一下怎么求(C),我们可以通过向量的叉积来算.

    因为(C)要离(AB)最远等价于(S_{Delta ABC})最大即:(overrightarrow{A C}*overrightarrow{A B})最小

    [overrightarrow{A C}*overrightarrow{A B} ]

    [=(X_B-X_A)*(Y_C-Y_A)-(Y_B-Y_A)*(X_C-X_A) ]

    [=(X_B-X_A)*Y_C+(Y_A-Y_B)*X_C+ans ]

    ans为一个常数,不用管他.

    然后我们直接将权值/费用改为((X_B-X_A)*b+(Y_A-Y_B)*a)在跑一遍(km/)费用流即可

    (luogu)没过T了,(bzoj)过了

    (Code)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int read() {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    struct node {
        int x,y;
        bool operator == (const node &z)const {
            return x==z.x&&y==z.y;
        }
    };
    node operator - (const node & a , const node & b) {
        return (node) {
            a.x-b.x,a.y-b.y
        };
    }
    int calc(node x, node y) {
        return (x.x * y.y) - (x.y * y.x);
    }
    node minx;
    struct node1 {
        int to,next,v,w;
    } a[1000001];
    int dis[100001],f[100001],pre[100001],fa[100001],s,t,n,m,head[100001],cnt,x,y,z,c,A[100][100],B[100][100];
    void add(int x,int y,int c,int v) {
        a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,a[cnt].w=v,head[x]=cnt;
        a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,a[cnt].w=-v,head[y]=cnt;
    }
    queue < int > q;
    int spfa() {
        q.push(s);
        for(int i=s; i<=t; i++)
            dis[i]=2147483647,f[i]=0;
        f[s]=1,dis[s]=0;
        int inf=dis[s+1];
        while(!q.empty()) {
            int now=q.front();
            q.pop(),f[now]=0;
            for(int i=head[now]; i; i=a[i].next) {
                int v=a[i].to;
                if(dis[v]>dis[now]+a[i].w&&a[i].v) {
                    dis[v]=dis[now]+a[i].w,pre[v]=i,fa[v]=now;
                    if(!f[v])
                        f[v]=1,q.push(v);
                }
            }
        }
        if(dis[t]!=inf)
            return 1;
        return 0;
    }
    int ans1,ans,minn=2147483647;
    void answer() {
        while(spfa()) {
            int minx=2147483647;
            for(int i=t; i!=s; i=fa[i])
                minx=min(minx,a[pre[i]].v);
            ans+=minx,ans1+=dis[t]*minx;
            for(int i=t; i!=s; i=fa[i])
                a[pre[i]].v-=minx,(pre[i]%2)?a[pre[i]+1].v+=minx:a[pre[i]-1].v+=minx;
        }
    }
    node work(int fx,int fy) {
        cnt=0,s=0,t=2*n+1;
        for(int i=s; i<=t; i++)
            head[i]=0;
        for(int i=1; i<=n; i++) {
            add(s,i,1,0),add(i+n,t,1,0);
            for(int j=1; j<=n; j++)
                add(i,j+n,1,A[i][j]*fx+B[i][j]*fy);
        }
        answer();
        int x=0,y=0;
        for(int i=1; i<=n; i++)
            for(int j=head[i]; j; j=a[j].next)
                if(!a[j].v&&a[j].to)
                    x+=A[i][a[j].to-n],y+=B[i][a[j].to-n];
        node ans2;
        ans2.x=x,ans2.y=y;
        if(x*y<minn)
            minn=x*y;
        return ans2;
    }
    void devide(node l,node r) {
        node mid=work(l.y-r.y,r.x-l.x);
        if(l==mid||mid==r) return ;
        devide(l,mid),devide(mid,r);
    }
    main() {
        int T=read();
        node l,r;
        while(T--) {
            n=read(),minn=2147483647;
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    A[i][j]=read();
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    B[i][j]=read();
            l=work(1,0),r=work(0,1);
            devide(l,r);
            printf("%d
    ",minn);
        }
    }
    
  • 相关阅读:
    岩石圈
    地球及其圈层结构
    如何请教一个技术问题
    中国游戏路在何方?
    5.4删除二叉搜索树的任意元素
    5.3 删除二叉搜索树的最大元素和最小元素
    uni-app开发小程序准备阶段
    5.2二叉搜索树遍历(前序、中序、后序、层次、广度优先遍历)
    5.1二叉搜索树基础
    【loj
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10404436.html
Copyright © 2011-2022 走看看