zoukankan      html  css  js  c++  java
  • XWW的难题(bzoj 3698)

    Description

    XWW是个影响力很大的人,他有很多的追随者。这些追随者都想要加入XWW教成为XWW的教徒。但是这并不容易,需要通过XWW的考核。
    XWW给你出了这么一个难题:XWW给你一个N*N的正实数矩阵A,满足XWW性。
    称一个N*N的矩阵满足XWW性当且仅当:(1)A[N][N]=0;(2)矩阵中每行的最后一个元素等于该行前N-1个数的和;(3)矩阵中每列的最后一个元素等于该列前N-1个数的和。
    现在你要给A中的数进行取整操作(可以是上取整或者下取整),使得最后的A矩阵仍然满足XWW性。同时XWW还要求A中的元素之和尽量大。

    Input

    第一行一个整数N,N ≤ 100。
    接下来N行每行包含N个绝对值小于等于1000的实数,最多一位小数。

    Output

    输出一行,即取整后A矩阵的元素之和的最大值。无解输出No。

    Sample Input

    4
    3.1 6.8 7.3 17.2
    9.6 2.4 0.7 12.7
    3.6 1.2 6.5 11.3
    16.3 10.4 14.5 0

    Sample Output

    129

    HINT

    【数据规模与约定】

    有10组数据,n的大小分别为10,20,30...100。

    【样例说明】

    样例中取整后满足XWW性的和最大的矩阵为:

    3 7 8 18

    10 3 0 13

    4 1 7 12

    17 11 15 0

    /*
        上下界最大流。
        建立源点SS,从SS向i连一条上下界为(floor(a[i][n]),ceil(a[i][n]))的边;
        建立源点TT,从i'向TT连一条上下界为(floor(a[n][i]),ceil(a[n][i]))的边;
        建立i->i'上下界为(floor(a[i][j]),ceil(a[i][j]))的边。
        跑上下界最大流。 
    */
    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #define N 210
    #define M 21000
    #define inf 1000000000
    using namespace std;
    int down[N][N],up[N][N],head[N],dis[N],s[N],n,cnt=1,SS,TT,S,T;
    struct node{int v,f,pre;}e[M];
    queue<int> q;
    void add(int u,int v,int f){
        e[++cnt].v=v;e[cnt].f=f;e[cnt].pre=head[u];head[u]=cnt;
        e[++cnt].v=u;e[cnt].f=0;e[cnt].pre=head[v];head[v]=cnt;
    }
    bool bfs(){
        memset(dis,-1,sizeof(dis));
        q.push(S);dis[S]=0;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].pre){
                if(!e[i].f||dis[e[i].v]!=-1) continue;
                dis[e[i].v]=dis[u]+1;
                q.push(e[i].v);
            }
        }
        return dis[T]!=-1;
    }
    int dinic(int x,int f){
        int rest=f;
        if(x==T) return f;
        for(int i=head[x];i;i=e[i].pre){
            if(!e[i].f||dis[e[i].v]!=dis[x]+1) continue;
            int t=dinic(e[i].v,min(rest,e[i].f));
            e[i].f-=t;e[i^1].f+=t;rest-=t;
        }
        if(rest==f) dis[x]=-1;
        return f-rest;
    }
    int main(){
        scanf("%d",&n);
        SS=n*2+1;TT=n*2+2;S=n*2+3;T=n*2+4;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                double x;scanf("%lf",&x);
                down[i][j]=int(x);
                up[i][j]=int(x+0.99);
            }
        for(int i=1;i<n;i++){
            if(down[i][n]!=up[i][n]) add(SS,i,1);
            if(down[n][i]!=up[n][i]) add(i+n,TT,1);
            s[SS]+=down[i][n];s[i]-=down[i][n];
            s[i+n]+=down[n][i];s[TT]-=down[n][i];
        }
        for(int i=1;i<n;i++)
            for(int j=1;j<n;j++){
                if(down[i][j]!=up[i][j]) add(i,j+n,1);
                s[i]+=down[i][j];s[j+n]-=down[i][j];
            }
        int tot=0;
        for(int i=1;i<=T;i++){
            if(s[i]>0) add(i,T,s[i]),tot+=s[i];
            if(s[i]<0) add(S,i,-s[i]);
        }
        add(TT,SS,inf);
        int maxflow=0;
        while(bfs()) maxflow+=dinic(S,inf);
        if(maxflow!=tot) {printf("No");return 0;}
        maxflow=0;
        S=SS;T=TT;
        while(bfs()) maxflow+=dinic(S,inf);
        printf("%d",maxflow*3);
        return 0;
    }
  • 相关阅读:
    微信小程序(三)-事件绑定
    微信小程序(二)-语法学习
    微信小程序(一)-工具创建和结构配置说明 Stable Build
    ============================================ 微信小程序开发学习
    Vue学习笔记-Vue.js-2.X 学习(七)===>脚手架Vue-CLI(路由Router)
    Vue学习笔记-Vue.js-2.X 学习(六)===>脚手架Vue-CLI(项目说明-Babel)
    Vue学习笔记-Vue.js-2.X 学习(五)===>脚手架Vue-CLI(PyCharm)
    linux打包压缩命令汇总
    js中函数之函数名带括号与不带括号的区别
    $_FILES error(笔记)
  • 原文地址:https://www.cnblogs.com/harden/p/6629156.html
Copyright © 2011-2022 走看看