BZOJ 4500: 矩阵 差分约束

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=4500

题解:

从行向列建边,代表一个格子a[i][j],对每个顶点的所有操作可以合并在一起用sum[xi]表示,

那么题目相当于是要求sum[xi]+sum[xj]==a[xi][xj];

等价于:sum[xj]-(-sum[xi])==a[xi][xj]

等价于:sum[xj]-sum'[xi]<=a[xi][xj] && sum[xj]-sum'[xi]>=a[xi][xj]

等价于:sum[xj]<=sum'[xi]+w && sum'[xi]<=sum[xj]+(-w)

所有就可以用差分约束来做了。跑一遍最短路,判一下负环就可以了。

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

const int maxn = 2222;
const int INF = 0x3f3f3f3f;

struct Edge {
    int v, w;
    Edge(int v, int w) :v(v), w(w) {}
    Edge() {}
};

int n, m,k;
vector<Edge> egs;
vector<int> G[maxn];

void addEdge(int u, int v, int w) {
    G[u].push_back(egs.size());
    egs.push_back(Edge(v,w));
}

bool inq[maxn];
int cnt[maxn];
int d[maxn];
bool spfa() {
    memset(inq, 0, sizeof(inq));
    memset(cnt, 0, sizeof(cnt));
    for (int i = 0; i <= n + m; i++) d[i] = INF;
    queue<int> Q;
    d[0] = 0; inq[0] = true; Q.push(0);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        inq[u] = false;
        for (int i = 0; i < G[u].size(); i++) {
            Edge& e = egs[G[u][i]];
            if (d[e.v] > d[u] + e.w) {
                d[e.v] = d[u] + e.w;
                if (!inq[e.v]) {
                    Q.push(e.v);
                    inq[e.v] = true;
                    if (++cnt[e.v] > n+m+1) {
                        return false;
                    }
                }
            }
        }
    }
    return true;
}

void init() {
    for (int i = 0; i <= n + m; i++) G[i].clear();
    egs.clear();
}

int main() {
    int tc;
    scanf("%d", &tc);
    while (tc--) {
        scanf("%d%d%d", &n, &m, &k);
        init();
        for (int i = 0; i < k; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            addEdge(u, v+n, w);
            addEdge(v+n, u, -w);
        }
        for (int i = 1; i <= n + m; i++) {
            addEdge(0, i, 0);
        }
        if (spfa()) {
            puts("Yes");
        }
        else {
            puts("No");
        }
    }
    return 0;
}

/*
2
2 2 4
1 1 0
1 2 0
2 1 2
2 2 2
2 2 4
1 1 0
1 2 0
2 1 2
2 2 1
*/

 

posted @ 2016-05-28 00:37  fenicnn  阅读(190)  评论(0编辑  收藏  举报