zoukankan      html  css  js  c++  java
  • hdu_1565(网络流)

    解法一、网络流

    相邻的点染不同颜色:

      (行数+列数)为奇数的染成白色,(行数+列数)为偶数的染成白色

    source = 0, sink = n*n+1.

    source到每个白点连接,流量为白点的值

    黑点到sink连接,流量为黑点的值

    每个白点与其周围的黑点连接,流量为INT_MAX

    所有点的值的总和 - 最大流量 = 所求答案

    以下是抄来的原理:

      点覆盖集:无向图G的一个点集,使得该图中所有边都至少有一个端点在该集合内。

      最小点权覆盖集:在带点权无向图G中,点权之和最小的覆盖集。

      点独立集:无向图G的一个点集,使得任两个在该集合中的点在原图中都不相邻。
      最大点权独立集:在带权无向图G中,点权之和最大的独立集。


      定理:
        1. 二分图的最小点权覆盖集=最小割=最大流
        2. 二分图的最大点权独立集=总权-最小点权覆盖集

      1 #include <cstdio>
      2 #include <climits>
      3 #include <cstring>
      4 #include <queue>
      5 
      6 #define MAXN 20
      7 
      8 const int source = 0;
      9 int n, G[MAXN*MAXN+10][MAXN*MAXN+10], layer[MAXN*MAXN+10], total, sink;
     10 bool vis[MAXN*MAXN+10];
     11 
     12 bool bfs()
     13 {
     14     memset(layer, -1, sizeof(layer));
     15     std::queue<int> q;
     16     q.push(source);
     17     layer[source] = 0;
     18     while(q.empty()==false){
     19         int u = q.front();
     20         q.pop();
     21         for(int v = 1; v <= sink; ++v){
     22             if(layer[v] == -1 && G[u][v] > 0){
     23                 layer[v] = layer[u] + 1;
     24                 if(v == sink)
     25                     return true;
     26                 q.push(v);
     27             }
     28         }
     29     }
     30     return false;
     31 }
     32 
     33 int dinic()
     34 {
     35     int max_flow = 0;
     36     while(bfs() == true){
     37         memset(vis,false,sizeof(vis));
     38         vis[source] = true;
     39         int st[MAXN*MAXN+10];
     40         int top = 0;
     41         st[++top]= source;
     42         while(top > 0) {
     43             int u = st[top];
     44             if(u == sink) {
     45                 int current = INT_MAX;
     46                 int key_path;
     47                 for(int i = 1; i < top; ++i) {
     48                     int s = st[i];
     49                     int e = st[i+1];
     50                     if(current > G[s][e]) {
     51                         current = G[s][e];
     52                         key_path = i;
     53                     }
     54                 }
     55                 for(int i = 1; i < top; ++i) {
     56                     int s = st[i];
     57                     int e = st[i+1];
     58                     G[s][e] -= current;
     59                     G[e][s] += current;
     60                 }
     61 
     62                 max_flow += current;
     63                 while(top > key_path) {
     64                     vis[st[top--]] = false;
     65                 }
     66             }
     67             else {
     68                 int v;
     69                 for(v= 1; v <= sink; ++v) {
     70                     if(layer[v] == layer[u]+1 && vis[v] == false && G[u][v] > 0) {
     71                         vis[v] = true;
     72                         st[++top] = v;
     73                         break;
     74                     }
     75                 }
     76                 if(v == sink+1) {
     77                     top--;
     78                 }
     79             }
     80         }
     81     }
     82     return max_flow;
     83 }
     84 
     85 void init()
     86 {
     87     memset(G, 0, sizeof(G));
     88     total = 0;
     89     sink = n*n+1;
     90     for(int i = 1, input_buffer; i <= n*n; ++i){
     91         scanf("%d", &input_buffer);
     92         total += input_buffer;
     93         int row = (i-0.1) / n + 1;
     94         int column = (i % n == 0) ? (n) : (i % n);
     95         // if (row + column) is odd number, link source to this cell.
     96         if( (row + column)&1 ){
     97             G[source][i] = input_buffer;
     98 
     99             if(i%n != 1)
    100                 G[i][i-1] = INT_MAX;
    101             if(i%n != 0)
    102                 G[i][i+1] = INT_MAX;
    103             if(i > n)
    104                 G[i][i-n] = INT_MAX;
    105             if(i <= n*n-n)
    106                 G[i][i+n] = INT_MAX;
    107         }
    108         // if (row + column) is even number, link this cell to sink.
    109         else
    110             G[i][sink] = input_buffer;
    111     }
    112 }
    113 
    114 int main(int argc, char const *argv[])
    115 {
    116     // freopen("in", "r", stdin);
    117     while(~scanf("%d", &n)){
    118         init();
    119         printf("%d
    ", total - dinic());
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    Uva 10935 Throwing cards away I
    Uva 3226 Symmetry
    eclipse @ 注释为何一写就报错
    2015省赛小感想
    Zoj 3842 Beauty of Array
    fedora 设置命令别名
    Uva220 Othello
    工作小技巧积累
    SSL介绍与Java实例
    一个完整的SSL连接建立过程
  • 原文地址:https://www.cnblogs.com/takeoffyoung/p/4316980.html
Copyright © 2011-2022 走看看