UVa #11082 Matrix Decompressing (例题11-8)

86 篇文章 0 订阅

这道题的建模有点像神经网络的隐层和输出层的设计。把一整行/列的和当作输入/输出结点,则它们之间的每条边就是一个矩阵内的元素。



Run Time: 0.029s

#define UVa  "LT11-8.11082.cpp"		//Matrix Decompressing
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<queue>
using namespace std;


//Global Variables. Reset upon Each Case!
const int maxn = 40 + 5, INF = 1<<30;
int T, R, C;
int A[maxn], B[maxn], Ap[maxn], Bp[maxn];
/
struct Edge {
    int from, to, cap, flow;
    Edge(int a, int b, int c): from(a), to(b), cap(c), flow(0) {}
};

struct EdmondsKarp {
    vector<Edge> edges;
    vector<int> G[maxn];
    int a[maxn], p[maxn];

    void init() {
        edges.clear();
        for(int i = 0; i < maxn; i ++) G[i].clear();
    }
    void addEdge(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap));
        edges.push_back(Edge(to, from, 0));
        G[from].push_back(edges.size() - 2);
        G[to].push_back(edges.size() - 1);
    }

    int maxFlow(int s, int t) {
        int flow = 0;
        for(;;) {
            memset(a, 0, sizeof(a));
            a[s] = INF;
            queue<int> q;
            q.push(s);
            while(!q.empty()) {
                int x = q.front(); q.pop();
                for(int i = 0; i < G[x].size(); i ++) {
                    Edge& e = edges[G[x][i]];
                    int y = e.to;
                    if(!a[y] && e.cap > e.flow) {
                        a[y] = min(a[x], e.cap - e.flow);
                        q.push(y);
                        p[y] = G[x][i];
                    }
                }
                if(a[t]) break;
            }
            if(!a[t]) break;
            for(int u = t; u != s; u = edges[p[u]].from) {
                edges[p[u]].flow += a[t];
                edges[p[u]^1].flow -= a[t];
            }
            flow += a[t];
        }
        return flow;
    }
};


void init() {
    cin>>R>>C;
    for(int i = 0; i < R; i ++) cin>>A[i];
    for(int i = 0; i < C; i ++) cin>>B[i];
    for(int i = 0; i < R; i ++) {
        Ap[i] = A[i] - ((i)?A[i-1]:0);
    }
    for(int i = 0; i < C; i ++) {
        Bp[i] = B[i] - ((i)?B[i-1]:0);
    }
}

void solve() {
    EdmondsKarp EK;
    EK.init();
    int s = R+C+1, t = R+C+2;
    for(int i = 0; i < R; i ++)
        EK.addEdge(s, i, Ap[i]-C);
    for(int i = 0; i < C; i ++)
        EK.addEdge(R+i, t, Bp[i]-R);
    for(int i = 0; i < R; i ++)
        for(int j = 0; j < C; j ++)
            EK.addEdge(i, R+j, 19);
    int ans[maxn][maxn];
    EK.maxFlow(s, t);
    for(int i = 0; i < EK.edges.size(); i ++) {
        Edge& e = EK.edges[i];
        ans[e.from][e.to-R] = e.flow;
    }
    for(int i = 0; i < R; i ++) {
        for(int j = 0; j < C; j ++)
            printf("%d ", ans[i][j]+1);
        printf("\n");
    }
    printf("\n");
}

int main() {
    cin>>T;
    for(int kase = 1; kase <= T; kase ++) {
        printf("Matrix %d\n", kase);
        init();
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值