zoukankan      html  css  js  c++  java
  • [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;                                                                       //
    }                                                                                   //
                                                                                        //
                                                                                        //
                                                                                        //
    /* ******************************************************************************** */
  • 相关阅读:
    2021年下半年北京市中小学教师资格考试笔试报名公告
    高效演讲
    php的Allowed memory size of 134217728 bytes exhausted问题解决办法
    1111error
    http 500 错误
    xshell连接centons
    Vue 计算属性
    Vue 自定义指令
    Vue 事件绑定
    Vue v-cloak指令解决插值表达式“闪动”问题
  • 原文地址:https://www.cnblogs.com/jklongint/p/4688368.html
Copyright © 2011-2022 走看看