• HDU 4888 Redraw Beautiful Drawings (2014-多校3-1002,最大流,判最大流有多解)


    题目:

    http://acm.hdu.edu.cn/showproblem.php?pid=4888

    题意:

    给一个n*m的矩阵的n行之和和m列之和以及限制k,使用0-k的数字填充矩阵使得其行与列之和为给定值

    如果不行则输出Impossible

    如果有多解则输出Not Unique

    如果有一解则输出Unique,并输出构造的矩阵

    方法:

    最大流,判最大流有多解

    1、建图:

    每一行一个点,每一列一个点

    源点与第i个行点连边,权值为第i行之和

    第j个列点与汇点连边,权值为第j行之和

    第i个行点与第j个列点连边,权值为k

    2、跑最大流

    3、如果源点与n个行点都流满且m个列点与汇点都流满,则有解,否则无解

    4、判最大流有多解:

    如果有多解,则某两点流量可以为(f1,f2),(f1-f,f2+f),所以可以根据这个结论判最大流是否有多解:

    在残余网络中,如果存在大小大于2的环,则可以出现上述情况,即:有多解

     1 bool dfsc(int u, int fa)
     2 {
     3     vis[u] = 1;
     4     for (int i = head[u]; ~i; i = edge[i].next)
     5     {
     6         int v = edge[i].v;
     7         if (v == fa || edge[i].flow == edge[i].cap) continue;
     8         if (vis[v] || dfsc(v, u)) return 1;
     9     }
    10     vis[u] = 0;
    11     return 0;
    12 }
    13 bool check()
    14 {
    15     memset(vis, 0, sizeof(vis));
    16     for (int i = 2; i < N + 2; i++)
    17     {
    18         if (!vis[i])
    19         {
    20             vis[i] = 1;
    21             if (dfsc(i, i)) return 0;
    22             vis[i] = 0;
    23         }
    24     }
    25     return 1;
    26 }

    5、构造矩阵:

    第i个行点与第j个列点的流量即为(i,j)的值

    代码:

      1 // #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <cstdio>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <set>
      8 #include <list>
      9 #include <map>
     10 #include <iterator>
     11 #include <cstdlib>
     12 #include <vector>
     13 #include <queue>
     14 #include <stack>
     15 #include <algorithm>
     16 #include <functional>
     17 using namespace std;
     18 typedef long long LL;
     19 #define ROUND(x) round(x)
     20 #define FLOOR(x) floor(x)
     21 #define CEIL(x) ceil(x)
     22 // const int maxn = 0;
     23 // const int maxm = 0;
     24 // const int inf = 0x3f3f3f3f;
     25 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     26 const double INF = 1e30;
     27 const double eps = 1e-6;
     28 const int P[4] = {0, 0, -1, 1};
     29 const int Q[4] = {1, -1, 0, 0};
     30 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     31 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     32 
     33 /**
     34 *最大流最小割:加各种优化的Dinic算法($O(V^2E)$)
     35 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇)
     36 *输出:Dinic(NdFlow)(最大流),MinCut()(最小割)(需先求最大流)
     37 *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找
     38 */
     39 const int maxn = 810;
     40 const int maxm = 400010;
     41 const int inf = 0x3f3f3f3f;
     42 struct Edge
     43 {
     44     int u, v;
     45     int cap, flow;
     46     int next;
     47 } edge[maxm];
     48 int head[maxn], en; //需初始化
     49 int n, m, d[maxn], cur[maxn];
     50 int st, ed;
     51 bool vis[maxn];
     52 void addse(int u, int v, int cap, int flow)
     53 {
     54     edge[en].u = u;
     55     edge[en].v = v;
     56     edge[en].cap = cap;
     57     edge[en].flow = flow;
     58     edge[en].next = head[u];
     59     head[u] = en++;
     60     cur[u] = head[u];
     61 }
     62 void adde(int u, int v, int cap)
     63 {
     64     addse(u, v, cap, 0);
     65     addse(v, u, 0, 0); //注意加反向0边
     66 }
     67 bool BFS()
     68 {
     69     queue<int> Q;
     70     memset(vis, 0, sizeof(vis));
     71     Q.push(st);
     72     d[st] = 0;
     73     vis[st] = 1;
     74     while (!Q.empty())
     75     {
     76         int u = Q.front();
     77         Q.pop();
     78         for (int i = head[u]; i != -1; i = edge[i].next)
     79         {
     80             int v = edge[i].v;
     81             int w = edge[i].cap - edge[i].flow;
     82             if (w > 0 && !vis[v])
     83             {
     84                 vis[v] = 1;
     85                 Q.push(v);
     86                 d[v] = d[u] + 1;
     87                 if (v == ed) return 1;
     88             }
     89         }
     90     }
     91     return false;
     92 }
     93 int Aug(int u, int a)
     94 {
     95     if (u == ed) return a;
     96     int aug = 0, delta;
     97     for (int &i = cur[u]; i != -1; i = edge[i].next)
     98     {
     99         int v = edge[i].v;
    100         int w = edge[i].cap - edge[i].flow;
    101         if (w > 0 && d[v] == d[u] + 1)
    102         {
    103             delta = Aug(v, min(a, w));
    104             if (delta)
    105             {
    106                 edge[i].flow += delta;
    107                 edge[i ^ 1].flow -= delta;
    108                 aug += delta;
    109                 if (!(a -= delta)) break;
    110             }
    111         }
    112     }
    113     if (!aug) d[u] = -1;
    114     return aug;
    115 }
    116 int Dinic(int NdFlow)
    117 {
    118     int flow = 0;
    119     while (BFS())
    120     {
    121         memcpy(cur, head, sizeof(int) * (n + 1));
    122         flow += Aug(st, inf);
    123         /*如果超过指定流量就return 掉*/
    124         if (NdFlow == inf) continue;
    125         if (flow > NdFlow) break;
    126     }
    127     return flow;
    128 }
    129 /*残余网络*/
    130 void Reduce()
    131 {
    132     for (int i = 0; i < en; i++) edge[i].cap -= edge[i].flow;
    133 }
    134 /*清空流量*/
    135 void ClearFlow()
    136 {
    137     for (int i = 0; i < en; i++) edge[i].flow = 0;
    138 }
    139 /*求最小割*/
    140 vector<int> MinCut()
    141 {
    142     BFS();
    143     vector<int> ans;
    144     for (int u = 0; u < n; u++)
    145     {
    146         if (!vis[u]) continue;
    147         for (int i = head[u]; i != -1; i = edge[i].next)
    148         {
    149             if (i & 1) continue; /*忽略反向边*/
    150             int v = edge[i].v;
    151             int w = edge[i].cap;
    152             if (!vis[v] && w > 0) ans.push_back(i);
    153         }
    154     }
    155     return ans;
    156 }
    157 
    158 int N, M, K;
    159 int a[maxn], b[maxn];
    160 int mtx[410][410];
    161 void init()
    162 {
    163     memset(head, -1, sizeof(head));
    164     en = 0;
    165 }
    166 void input()
    167 {
    168     for (int i = 0; i < N; i++)
    169         scanf("%d", &a[i]);
    170     for (int i = 0; i < M; i++)
    171         scanf("%d", &b[i]);
    172 }
    173 void debug()
    174 {
    175     //
    176 }
    177 void build()
    178 {
    179     st = 0, ed = 1;
    180     n = N + M + 2;
    181     for (int i = 0; i < N; i++)
    182     {
    183         adde(st, i + 2, a[i]);
    184     }
    185     for (int i = 0; i < M; i++)
    186     {
    187         adde(i + N + 2, ed, b[i]);
    188     }
    189     for (int i = 0; i < N; i++)
    190     {
    191         for (int j = 0; j < M; j++)
    192         {
    193             adde(i + 2, j + N + 2, K);
    194         }
    195     }
    196 }
    197 bool dfsc(int u, int fa)
    198 {
    199     vis[u] = 1;
    200     for (int i = head[u]; ~i; i = edge[i].next)
    201     {
    202         int v = edge[i].v;
    203         if (v == fa || edge[i].flow == edge[i].cap) continue;
    204         if (vis[v] || dfsc(v, u)) return 1;
    205     }
    206     vis[u] = 0;
    207     return 0;
    208 }
    209 bool check()
    210 {
    211     memset(vis, 0, sizeof(vis));
    212     for (int i = 2; i < N + 2; i++)
    213     {
    214         if (!vis[i])
    215         {
    216             vis[i] = 1;
    217             if (dfsc(i, i)) return 0;
    218             vis[i] = 0;
    219         }
    220     }
    221     return 1;
    222 }
    223 void solve()
    224 {
    225     build();
    226     Dinic(inf);
    227     // cout << "flow: " << Dinic(inf) << endl;
    228     int flag = 1;
    229     for (int i = head[st]; ~i; i = edge[i].next)
    230     {
    231         if (i & 1) continue;
    232         if (edge[i].cap > edge[i].flow)
    233         {
    234             flag = 0;
    235             break;
    236         }
    237     }
    238     for (int i = head[ed]; ~i; i = edge[i].next)
    239     {
    240         if (i & 0) continue;
    241         if (-edge[i].flow < edge[i ^ 1].flow)
    242         {
    243             flag = 0;
    244             break;
    245         }
    246     }
    247     if (!flag)
    248     {
    249         puts("Impossible");
    250         return;
    251     }
    252     if (!check())
    253     {
    254         puts("Not Unique");
    255         return;
    256     }
    257     for (int u = 0; u < N; u++)
    258     {
    259         for (int i = head[u + 2]; ~i; i = edge[i].next)
    260         {
    261             if (i & 1) continue;
    262             int v = edge[i].v - N - 2;
    263             mtx[u][v] = edge[i].flow;
    264         }
    265     }
    266     puts("Unique");
    267     for (int i = 0; i < N; i++)
    268     {
    269         for (int j = 0; j < M; j++)
    270         {
    271             if (j < M - 1) printf("%d ", mtx[i][j]);
    272             else printf("%d
    ", mtx[i][j]);
    273         }
    274     }
    275 }
    276 void output()
    277 {
    278     //
    279 }
    280 int main()
    281 {
    282     // int size = 256 << 20; // 256MB
    283     // char *p = (char *)malloc(size) + size;
    284     // __asm__("movl %0, %%esp
    " :: "r"(p));
    285 
    286     // std::ios_base::sync_with_stdio(false);
    287 #ifndef ONLINE_JUDGE
    288     freopen("in.cpp", "r", stdin);
    289 #endif
    290 
    291     while (~scanf("%d%d%d", &N, &M, &K))
    292     {
    293         init();
    294         input();
    295         solve();
    296         output();
    297     }
    298     return 0;
    299 }
    HDU 4888
  • 相关阅读:
    Paddle和PaddleNLP的简介与使用
    Hangfire 使用笔记 任务可以分离到别的项目中,无需重复部署Hangfire,通过API方式通信。
    DeprecationWarning: find_element_by_* commands are deprecated. Please use find_element() instead driver.find_element_by_class_name('content-wrapper-inner').click()
    图片反防盗链
    onsubmit=return false阻止form表单提交
    360极速浏览器安装vue-devtools插件
    Node.js安装详细步骤教程(Windows版)
    C/C++ for Visual Studio Code
    mysql 利用ibd文件恢复数据库
    解决 本地计算机上的MySQL80服务启动后停止的问题!!!
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3878395.html
Copyright © 2020-2023  润新知