zoukankan      html  css  js  c++  java
  • hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975


    Problem Description
    Dragon is studying math. One day, he drew a table with several rows and columns, randomly wrote numbers on each elements of the table. Then he counted the sum of each row and column. Since he thought the map will be useless after he got the sums, he destroyed the table after that.

    However Dragon's mom came back and found what he had done. She would give dragon a feast if Dragon could reconstruct the table, otherwise keep Dragon hungry. Dragon is so young and so simple so that the original numbers in the table are one-digit number (e.g. 0-9).

    Could you help Dragon to do that?
     

    Input
    The first line of input contains only one integer, T(<=30), the number of test cases. Following T blocks, each block describes one test case.

    There are three lines for each block. The first line contains two integers N(<=500) and M(<=500), showing the number of rows and columns.

    The second line contains N integer show the sum of each row.

    The third line contains M integer show the sum of each column.
     

    Output
    Each output should occupy one line. Each line should start with "Case #i: ", with i implying the case number. For each case, if we cannot get the original table, just output: "So naive!", else if we can reconstruct the table by more than one ways, you should output one line contains only: "So young!", otherwise (only one way to reconstruct the table) you should output: "So simple!".
     

    Sample Input
    3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
     

    Sample Output
    Case #1: So simple! Case #2: So naive! Case #3: So young!
     

    Source


    题意:

    给出每行每列的和,问是否存在这种表格;每一个小格放的数字仅仅能是0--9。


    官方题解:http://blog.sina.com.cn/s/blog_6bddecdc0102v01l.html


    代码例如以下:(套用别人HDU4888的模板)

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    using namespace std;
    #define ll __int64
    #define eps 1e-8
    const ll Mod=(1e9+7);
    const int maxn = 510;
    const int maxm = 50100;
    
    int n,m,k;
    int r[maxn],c[maxn];
    int ma[maxn][maxn];
    
    
    const int maxnode = 10000 + 5;
    const int maxedge = 2*1000000 + 5;
    const int oo = 1000000000;
    int node, src, dest, nedge;
    int head[maxnode], point[maxedge], next1[maxedge], flow[maxedge], capa[maxedge];//point[x]==y表示第x条边连接y,head,next为邻接表,flow[x]表示x边的动态值,capa[x]表示x边的初始值
    int dist[maxnode], Q[maxnode], work[maxnode];//dist[i]表示i点的等级
    void init(int _node, int _src, int _dest) //初始化,node表示点的个数,src表示起点,dest表示终点
    {
        node = _node;
        src = _src;
        dest = _dest;
        for (int i = 0; i < node; i++) head[i] = -1;
        nedge = 0;
    }
    void addedge(int u, int v, int c1, int c2) //添加一条u到v流量为c1,v到u流量为c2的两条边
    {
        point[nedge] = v, capa[nedge] = c1, flow[nedge] = 0, next1[nedge] = head[u], head[u] = (nedge++);
        point[nedge] = u, capa[nedge] = c2, flow[nedge] = 0, next1[nedge] = head[v], head[v] = (nedge++);
    }
    bool dinic_bfs()
    {
        memset(dist, 255, sizeof (dist));
        dist[src] = 0;
        int sizeQ = 0;
        Q[sizeQ++] = src;
        for (int cl = 0; cl < sizeQ; cl++)
            for (int k = Q[cl], i = head[k]; i >= 0; i = next1[i])
                if (flow[i] < capa[i] && dist[point[i]] < 0)
                {
                    dist[point[i]] = dist[k] + 1;
                    Q[sizeQ++] = point[i];
                }
        return dist[dest] >= 0;
    }
    int dinic_dfs(int x, int exp)
    {
        if (x == dest) return exp;
        for (int &i = work[x]; i >= 0; i = next1[i])
        {
            int v = point[i], tmp;
            if (flow[i] < capa[i] && dist[v] == dist[x] + 1 && (tmp = dinic_dfs(v, min(exp, capa[i] - flow[i]))) > 0)
            {
                flow[i] += tmp;
                flow[i^1] -= tmp;
                return tmp;
            }
        }
        return 0;
    }
    int dinic_flow()
    {
        int result = 0;
        while (dinic_bfs())
        {
            for (int i = 0; i < node; i++) work[i] = head[i];
            while (1)
            {
                int delta = dinic_dfs(src, oo);
                if (delta == 0) break;
                result += delta;
            }
        }
        return result;
    }
    //建图前,执行一遍init();
    //加边时,执行addedge(a,b,c,0),表示点a到b流量为c的边建成(注意点序号要从0開始)
    //求解最大流执行dinic_flow(),返回值即为答案
    
    
    bool judge(int sumrow)
    {
        int flow = 1,cost = 0;
        for(int i = 1; i <= n; i++)
            for(int j = n+1; j <= n+m; j ++)
                addedge(i,j,k,0);
        flow=dinic_flow();
        if(flow != sumrow)
            return false;
        return true;
    }
    int main()
    {
        //k为能填原图能填的数字的最大值
        int t;
        int cas = 0;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            k = 9;//最多能填9
            init(n+m+2,0,n+m+1);
            int flag = 0;
            int sumrow = 0,colrow = 0;
            for(int i = 1; i <= n; i++)
            {
                scanf("%d",&r[i]);
                addedge(0,i,r[i],0);
                sumrow += r[i];
                if(r[i]<0 || r[i]>m*k)
                    flag = 1;
            }
            for(int j = 1; j <= m; j ++)
            {
                scanf("%d",&c[j]);
                addedge(j+n,n+m+1,c[j],0);
                colrow += c[j];
                if(c[j]<0 || c[j]>n*k)
                    flag = 1;
            }
            if(sumrow != colrow)
            {
                printf("Case #%d: So naive!
    ",++cas);
                continue;
            }
            if(!judge(sumrow))
                flag = 1;
            if(flag == 1)
            {
                printf("Case #%d: So naive!
    ",++cas);
                continue;
            }
            memset(ma,-1,sizeof(ma));
            int i,j;
            for(i=1; i<=n; i++)
                if(r[i]==0)
                    for(j=1; j<=m; j++)
                        ma[i][j]=0;
            for(j=1; j<=m; j++)
                if(c[j]==0)
                    for(i=1; i<=n; i++)
                        ma[i][j]=0;
            int tt=2;
            int sum,num,temp;
            while(tt--)
            {
                for(i=1; i<=n; i++)
                {
                    if(r[i]==0)
                    {
                        for(j=1; j<=m; j++)
                            if(ma[i][j]==-1)
                                ma[i][j]=0;
                        continue;
                    }
                    sum=0;
                    num=0;
                    for(j=1; j<=m; j++)
                    {
                        if(ma[i][j]==-1)
                        {
                            num++;
                            temp=j;
                            sum+=min(k,c[j]);
                        }
                    }
                    if(num==1)
                    {
                        ma[i][temp]=r[i];
                        r[i]-=ma[i][temp];
                        c[temp]-=ma[i][temp];
                        continue;
                    }
                    else if(sum==r[i])
                    {
                        for(j=1; j<=m; j++)
                        {
                            if(ma[i][j]==-1)
                            {
                                ma[i][j]=min(k,c[j]);
                                r[i]-=ma[i][j];
                                c[j]-=ma[i][j];
                            }
                        }
                    }
                }
                for(j=1; j<=m; j++)
                {
                    if(c[j]==0)
                    {
                        for(i=1; i<=n; i++)
                            if(ma[i][j]==-1)
                                ma[i][j]=0;
                        continue;
                    }
                    sum=0;
                    num=0;
                    for(i=1; i<=n; i++)
                    {
                        if(ma[i][j]==-1)
                        {
                            num++;
                            temp=i;
                            sum+=min(k,r[i]);
                        }
                    }
                    if(num==1)
                    {
                        ma[temp][j]=c[j];
                        r[temp]-=ma[temp][j];
                        c[j]-=ma[temp][j];
                        continue;
                    }
                    else if(sum==c[j])
                    {
                        for(i=1; i<=n; i++)
                        {
                            if(ma[i][j]==-1)
                            {
                                ma[i][j]=min(k,r[i]);
                                r[i]-=ma[i][j];
                                c[j]-=ma[i][j];
                            }
                        }
                    }
                }
            }
            flag=0;
            for(i=1; i<=n; i++)
                if(r[i]!=0)
                {
                    flag=1;
                    break;
                }
            for(j=1; j<=m; j++)
                if(c[j]!=0)
                {
                    flag=1;
                    break;
                }
            if(flag==1)
                printf("Case #%d: So young!
    ",++cas);
            else
            {
                printf("Case #%d: So simple!
    ",++cas);
                /* for(i=1; i<=n; i++)
                 {
                     for(j=1; j<m; j++)
                         printf("%d ",ma[i][j]);
                     printf("%d
    ",ma[i][m]);
                 }*/
            }
        }
        return 0;
    }
    


  • 相关阅读:
    Linux之RPM 软件包管理
    软件开发模型之优缺点
    软件开发模型之迭代模型
    软件工程之软件开发模型类型
    软件开发模型之边做边改模型
    软件开发模型之螺旋模型
    软件开发模型之快速原型模型
    软件工程之软件开发模型介绍和选择
    卡内基的沟通原则
    软件开发模型之增量模型
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4502922.html
Copyright © 2011-2022 走看看