[hdu4888]最大流,判断最大流唯一性

题意:给一个n*m的矩形,往每个格子填0-k的数字,使得对第i行和为row[i],第i列和为col[i],问是否存在方案,方案是否唯一,如果方案唯一则输出具体方案。

思路:首先根据问题提取对象,行、列、格子、数,只有数可以连接其它的对象。从源点向第i行连一条容量为row[i]的有向边,从第i行向第i行的每个格子连一条容量为k的有向边,从每个格子向第i列(i为格子的列号)连一条容量为k的有向边,然后从第i列向汇点连一条容量为col[i]的边。这样建图以后,发现每个格子唯一连接一个行和一个列,也就是入度和出度均为1,那么格子其实就没有存在的必要了,直接从每行向每列连一条容量为k的有向边。如果最大流=Σrow[i]=Σcol[i],则表明有解。对于有多解的情况,只需判断残量网络是否存在有向环,因为在环上增减流量能得到不同的解而最大流不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* ******************************************************************************** */
#include <iostream>                                                                 //
#include <cstdio>                                                                   //
#include <cmath>                                                                    //
#include <cstdlib>                                                                  //
#include <cstring>                                                                  //
#include <vector>                                                                   //
#include <ctime>                                                                    //
#include <deque>                                                                    //
#include <queue>                                                                    //
#include <algorithm>                                                                //
#include <map>                                                                      //
using namespace std;                                                                //
                                                                                    //
#define pb push_back                                                                //
#define mp make_pair                                                                //
#define X first                                                                     //
#define Y second                                                                    //
#define all(a) (a).begin(), (a).end()                                               //
#define foreach(a, i) for (typeof(a.begin()) i = a.begin(); i != a.end(); ++ i)     //
#define fill(a, x) memset(a, x, sizeof(a))                                          //
                                                                                    //
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}    //
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>                    //
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;          //
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>      //
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>              //
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>   //
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}   //
                                                                                    //
typedef pair<intint> pii;                                                         //
typedef long long ll;                                                               //
typedef unsigned long long ull;                                                     //
                                                                                    //
template<typename T>bool umax(T&a, const T&b){return b>a?false:(a=b,true);}         //
template<typename T>bool umin(T&a, const T&b){return b<a?false:(a=b,true);}         //
template<typename T>                                                                //
void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}            //
template<typename T>                                                                //
void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}            //
                                                                                    //
/* -------------------------------------------------------------------------------- */
 
 
struct Dinic {
private:
    const static int maxn = 800 + 7;
    struct Edge {
        int from, to, cap;
        Edge(int u, int v, int w): from(u), to(v), cap(w) {}
    };
    int s, t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn], cur[maxn];
 
    bool bfs() {
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = true;
        while (!Q.empty()) {
            int x = Q.front(); Q.pop();
            for (int i = 0; i < G[x].size(); i ++) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap) {
                    vis[e.to] = true;
                    d[e.to] = d[x] + 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))) > 0) {
                e.cap -= f;
                edges[G[x][i] ^ 1].cap += f;
                flow += f;
                a -= f;
                if (a == 0) break;
            }
        }
        return flow;
    }
 
public:
    void clear() {
        for (int i = 0; i < maxn; i ++) G[i].clear();
        edges.clear();
        memset(d, 0, sizeof(d));
    }
    void add(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap));
        edges.push_back(Edge(to, from, 0));
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }
 
    int solve(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;
        while (bfs()) {
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, 1e9);
        }
        return flow;
    }
    bool FC(int fa, int rt) {
        vis[rt] = true;
        int sz = G[rt].size();
        for (int i = 0; i < sz; i ++) {
            Edge &e = edges[G[rt][i]];
            if (e.to != fa && e.cap) {
                if (vis[e.to]) return true;
                if (FC(rt, e.to)) return true;
            }
        }
        vis[rt] = false;
        return false;
    }
    bool get(int n, int m) {
        memset(vis, 0, sizeof(vis));
        for (int i = 1; i <= n; i ++) {
            if (FC(-1, i)) return true;
        }
        return false;
    }
    void out(int n, int m) {
        int now = n * 2 + m * 2 + 1;
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < m; j ++) {
                printf("%d%c", edges[now].cap, j == m - 1? ' ' ' ');
                now += 2;
            }
        }
    }
};
Dinic solver;
const int maxn = 407;
int row[maxn], col[maxn];
 
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt""r", stdin);
#endif // ONLINE_JUDGE
    int n, m, k;
    while (cin >> n >> m >> k) {
        solver.clear();
        int total = 0;
        for (int i = 1; i <= n; i ++) {
            int x;
            RI(x);
            solver.add(0, i, x);
            total += x;
        }
        for (int i = 1; i <= m; i ++) {
            int x;
            RI(x);
            solver.add(n + i, n + m + 1, x);
        }
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= m; j ++) {
                solver.add(i, n + j, k);
            }
        }
        int flow = solver.solve(0, n + m + 1);
        if (flow != total) puts("Impossible");
        else {
            if (solver.get(n, m)) puts("Not Unique");
            else {
                puts("Unique");
                solver.out(n, m);
            }
        }
    }
    return 0;                                                                       //
}                                                                                   //
                                                                                    //
                                                                                    //
                                                                                    //
/* ******************************************************************************** */
原文地址:https://www.cnblogs.com/jklongint/p/4688368.html