码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4975 A simple Gaussian elimination problem.(网络流,判断矩阵是否存在)

时间:2014-08-21 22:56:35      阅读:527      评论:0      收藏:0      [点我收藏+]

标签:des   style   http   color   os   io   for   ar   

题目链接: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。


代码如下:(套用别人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 = 2000000 + 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(){
    int t,cas=1;;
    scanf("%d",&t);
    while(t--)
    {
        printf("Case #%d: ",cas++);
        scanf("%d%d",&n,&m);
        k=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("So naive!\n");
            continue;
        }
        if(!judge(sumrow))
            flag = 1;
        if(flag == 1){
            printf("So naive!\n");
            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("So young!\n");
        else
        {
            printf("So simple!\n");
        }
    }
    return 0;
}


hdu 4975 A simple Gaussian elimination problem.(网络流,判断矩阵是否存在),布布扣,bubuko.com

hdu 4975 A simple Gaussian elimination problem.(网络流,判断矩阵是否存在)

标签:des   style   http   color   os   io   for   ar   

原文地址:http://blog.csdn.net/u012860063/article/details/38736763

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!