zoukankan      html  css  js  c++  java
  • 最大流判断方程是否有解

    Redraw Beautiful Drawings

    Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 3813 Accepted Submission(s): 1140


    Problem Description
    Alice and Bob are playing together. Alice is crazy about art and she has visited many museums around the world. She has a good memory and she can remember all drawings she has seen.

    Today Alice designs a game using these drawings in her memory. First, she matches K+1 colors appears in the picture to K+1 different integers(from 0 to K). After that, she slices the drawing into grids and there are N rows and M columns. Each grid has an integer on it(from 0 to K) representing the color on the corresponding position in the original drawing. Alice wants to share the wonderful drawings with Bob and she tells Bob the size of the drawing, the number of different colors, and the sum of integers on each row and each column. Bob has to redraw the drawing with Alice's information. Unfortunately, somtimes, the information Alice offers is wrong because of Alice's poor math. And sometimes, Bob can work out multiple different drawings using the information Alice provides. Bob gets confused and he needs your help. You have to tell Bob if Alice's information is right and if her information is right you should also tell Bob whether he can get a unique drawing.

    Input
    The input contains mutiple testcases.

    For each testcase, the first line contains three integers N(1 ≤ N ≤ 400) , M(1 ≤ M ≤ 400) and K(1 ≤ K ≤ 40).
    N integers are given in the second line representing the sum of N rows.
    M integers are given in the third line representing the sum of M columns.

    The input is terminated by EOF.

    Output
    For each testcase, if there is no solution for Bob, output "Impossible" in one line(without the quotation mark); if there is only one solution for Bob, output "Unique" in one line(without the quotation mark) and output an N * M matrix in the following N lines representing Bob's unique solution; if there are many ways for Bob to redraw the drawing, output "Not Unique" in one line(without the quotation mark).

    Sample Input
    2 2 4
    4 2
    4 2
    4 2 2
    2 2 5 0
    5 4
    1 4 3
    9
    1 2 3 3

    Sample Output
    Not Unique
    Impossible
    Unique
    1 2 3 3

    题意:给出一个矩阵的行数和列数,然后给出矩阵中的元素范围k([0,k]),接下来n个数代表每行的总和,然后m个数分别代表每列的总和,问该矩阵是否存在,若不存在输出Impossible,若存在并有多个解则输出Not Unique,否则输出Unique,并输出可行解。

    分析:首先建立二部图,源点和汇点,二部图的左部分为行(1-n),右部分为列(n+1,n+m),然后源点和行连接权值为行和,列和汇点建边权值是列和,然后每行和每列两两建边权值是k,首先判断sigma(row[i])和sigma(col[i])是否相等,若不相等,则判断Impossible,否则继续,然后判断最大流max_flow是不是和sigma(cow[i])相等,若不等,则Impossible,否则继续,接下来从列号开始对残留网络搜索,判断是否有环,若存在环并且环的顶点个数大于2,则存在多解,否则存在唯一解

    程序;

    #include"string.h"
    #include"stdio.h"
    #include"iostream"
    #include"algorithm"
    #include"queue"
    #include"stack"
    #include"stdlib.h"
    #include"math.h"
    #define inf 10000000
    #define INF 0x3f3f3f3f
    #define M 1009
    using namespace std;
    struct node
    {
        int u,v,w,next;
    }edge[M*400];
    int t,head[M],dis[M],use[M],work[M],mp[M][M];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w,int fw)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].w=w;
        edge[t].next=head[u];
        head[u]=t++;
        edge[t].u=v;
        edge[t].v=u;
        edge[t].w=fw;
        edge[t].next=head[v];
        head[v]=t++;
    }
    int bfs(int source,int sink)
    {
        queue<int>q;
        memset(dis,-1,sizeof(dis));
        q.push(source);
        dis[source]=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];~i;i=edge[i].next)
            {
                int v=edge[i].v;
                if(edge[i].w&&dis[v]==-1)
                {
                    dis[v]=dis[u]+1;
                    q.push(v);
                    if(v==sink)return 1;
                }
            }
        }
        return 0;
    }
    int dfs(int cur,int a,int sink)
    {
        if(cur==sink)return a;
        for(int &i=work[cur];~i;i=edge[i].next)
        {
            int v=edge[i].v;
            if(edge[i].w&&dis[v]==dis[cur]+1)
            {
                int tt=dfs(v,min(a,edge[i].w),sink);
                if(tt)
                {
                    edge[i].w-=tt;
                    edge[i^1].w+=tt;
                    return tt;
                }
            }
        }
        return 0;
    }
    int Dinic(int source,int sink)
    {
        int ans=0;
        while(bfs(source,sink))
        {
            memcpy(work,head,sizeof(head));
            while(int tt=dfs(source,inf,sink))
                ans+=tt;
        }
        return ans;
    }
    int DFS(int u,int id)
    {
        use[u]=1;
        for(int i=head[u];~i;i=edge[i].next)
        {
            int v=edge[i].v;
            if(id==(i^1))continue;
            if(edge[i].w)
            {
                if(use[v])
                    return 1;
                if(DFS(v,i))
                    return 1;
            }
        }
        use[u]=0;
        return 0;
    }
    int solve(int n,int m)
    {
        memset(use,0,sizeof(use));
        for(int i=1;i<=n;i++)
        {
            if(DFS(i,-1))
                return 1;
        }
        return 0;
    }
    int main()
    {
        int n,m,k,row,col;
        while(scanf("%d%d%d",&n,&m,&k)!=-1)
        {
            init();
            int rows=0,cols=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&row);
                add(0,i,row,0);
                rows+=row;
            }
            for(int i=1;i<=m;i++)
            {
                scanf("%d",&col);
                add(i+n,m+n+1,col,0);
                cols+=col;
            }
            if(cols!=rows)
            {
                printf("Impossible
    ");
                continue;
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    add(i,j+n,k,0);
                }
            }
            int ans=Dinic(0,m+n+1);
            int msg=solve(n,m);
            if(ans!=rows)
                printf("Impossible
    ");
            else if(msg)
                printf("Not Unique
    ");
            else
            {
                printf("Unique
    ");
                for(int i=(m+n)*2;i<t;i+=2)
                {
                    int u=edge[i].u;
                    int v=edge[i].v;
                    int w=edge[i^1].w;
                    mp[u][v-n]=w;
                }
                for(int i=1;i<=n;i++)
                {
                    for(int j=1;j<=m;j++)
                    {
                        if(j==1)
                        printf("%d",mp[i][j]);
                        else
                            printf(" %d",mp[i][j]);
                    }
                    printf("
    ");
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    SqlSelect记录搜索
    SqlSelect在查询结果前面加一列序号列
    关于MMC不能打开文件C:\Program Files\Microsoft SQL Server\80\Tools\Binn\SQL Server Enterprise Manager.MSC可能是由于文件不存在,不是一个MMC控制台,或者用后来的MMC版本创建。也可能你没有访问此文件的足够权限
    IsPostBack郁闷
    查询值的数目与目标字段中的数目不同
    SqlServer2000数据库备份
    三种antiTNF制剂生物学剂量增加、非生物制剂和类固醇强化作用的差异:来自临床实践的证据
    三种影像学方法证实依那西普治疗银屑病关节炎有关节修复作用
    北美地区早期和长期类风湿性关节炎患者应用依那西普10年以上的安全性和有效性
    肿瘤坏死因子(TNF)阻断剂治疗幼年型银屑病关节炎: 有效吗
  • 原文地址:https://www.cnblogs.com/mypsq/p/4481207.html
Copyright © 2011-2022 走看看