• UVA


    题目大意:给出一个R行C列的矩阵,如今给出他的前1-R行和 && 前1-C列和,问这个矩阵原来是如何的,要求每一个元素大小在1-20之间

    解题思路:将每一行连接到超级源点,容量为该行的和-列数
    将每一列连接到超级汇点,容量为该列的和-行数
    接着将每行连接到该行的每一个元素,容量为19
    将每一个元素连接到元素所在列。容量为19
    为什么容量为19,由于跑最大流的时候有可能边的流量为0,而他要求的是每一个数的范围在1-20之间,所以最后的答案都要加上1。这也解释了为什么连接到超级源点和超级汇点的容量要减去对应的值

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    #define N 1010
    #define INF 0x3f3f3f3f
    
    struct Edge{
        int from, to, cap, flow;
        Edge() {}
        Edge(int from, int to, int cap, int flow) : from(from), to(to), cap(cap), flow(flow) {}
    };
    
    struct Dinic{
        int n, m, s, t;
        vector<Edge> edges;
        vector<int> G[N];
        bool vis[N];
        int d[N], cur[N];
    
        void init(int n) {
            this->n = n;
            for (int i = 0; i <= n; i++) {
                G[i].clear();
            }
            edges.clear();
        }
    
        void AddEdge(int from, int to, int cap) {
            edges.push_back(Edge(from, to, cap, 0));
            edges.push_back(Edge(to, from, 0, 0));
            int m = edges.size();
            G[from].push_back(m - 2);
            G[to].push_back(m - 1);
        } 
    
        bool BFS() {
            memset(vis, 0, sizeof(vis));
            queue<int> Q;
            Q.push(s);
            vis[s] = 1;
            d[s] = 0;
    
            while (!Q.empty()) {
                int u = Q.front();
                Q.pop();
                for (int i = 0; i < G[u].size(); i++) {
                    Edge &e = edges[G[u][i]];
                    if (!vis[e.to] && e.cap > e.flow) {
                        vis[e.to] = true;
                        d[e.to] = d[u] + 1;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
    
        int DFS(int x, int a) {
            if (x == t || a == 0)
                return a;
    
            int flow = 0, f;
            for (int i = cur[x]; i < G[x].size(); i++) {
                Edge &e = edges[G[x][i]];
                if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
                    e.flow += f;
                    edges[G[x][i] ^ 1].flow -= f;
                    flow += f;
                    a -= f;
                    if (a == 0)
                        break;
                }
            }
            return flow;
        }
    
        int Maxflow(int s, int t) {
            this->s = s; this->t = t;
            int flow = 0;
            while (BFS()) {
                memset(cur, 0, sizeof(cur));
                flow += DFS(s, INF);
            }
            return flow;
        }
    };
    
    Dinic dinic;
    
    int n, m, cas = 1;
    int SumRow[N], SumCol[N], row[N], col[N];
    void init() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) 
            scanf("%d", &SumRow[i]);
        for (int i = 1; i <= m; i++)
            scanf("%d", &SumCol[i]);
    
        int source = 0, sink = n * m + n + m + 1;
        dinic.init(sink);
    
    
        row[1] = SumRow[1];
        dinic.AddEdge(source, n * m + 1, row[1] - m);
        for (int i = 2; i <= n; i++) {
            row[i] = SumRow[i] - SumRow[i - 1];
            dinic.AddEdge(source, n * m + i, row[i] - m);
        }
    
        col[1] = SumCol[1];
        dinic.AddEdge(n * m + n + 1, sink, SumCol[1] - n);
        for (int i = 2; i <= m; i++) {
            col[i] = SumCol[i] - SumCol[i - 1];
            dinic.AddEdge(n * m + n + i, sink, col[i] - n);
        }
    
        for (int i = 0; i < n; i++)
            for (int j = 1; j <= m; j++) {
                dinic.AddEdge(n * m + i + 1, i * m + j, 19);
                dinic.AddEdge(i * m + j, n * m + n + j, 19);
            }
        int ans = dinic.Maxflow(source, sink);
        printf("Matrix %d
    ", cas++);
        for (int i = 0; i < n; i++) {
            for (int j = 1; j <= m; j++) {
                if (j != 1)
                    printf(" ");
                for (int k = 0; k < dinic.G[i*m+j].size(); k++) {
                    int u = dinic.edges[dinic.G[i*m+j][k]].from;
                    int v = dinic.edges[dinic.G[i*m+j][k]].to;
    
                    if (u == i * m + j && v == n * m + n + j) {
                        printf("%d", dinic.edges[dinic.G[i*m+j][k]].flow + 1);
                        break;
                    }
                }
            }
            printf("
    ");
        }
    }
    
    int main() {
        int test;
        scanf("%d", &test);
        while (test--) {
            init();
            if (test)
                printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    【C/C++】例题5-4 反片语/算法竞赛入门经典/C++与STL入门/映射:map
    【VSCode】如何打开全屏模式/退出全屏模式
    【合同】电子科技大学/外协合同/采购合同
    新的开始
    ubuntu server 1604 搭建FTP服务器
    vim的查找功能
    Ubuntu改坏sudoers后无法使用sudo的解决办法
    ubuntu server 1604 配置网络信息
    ubuntu server 1604 关机和重启
    ubuntu server 1604 设置笔记本盒盖 不操作
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7248545.html
Copyright © 2020-2023  润新知