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\n", total - dinic());
120     }
121     return 0;
122 }
时间: 2024-10-10 23:58:20

hdu_1565(网络流)的相关文章

hiho 第118周 网络流四&#183;最小路径覆盖

描述 国庆期间正是旅游和游玩的高峰期. 小Hi和小Ho的学习小组为了研究课题,决定趁此机会派出若干个调查团去沿途查看一下H市内各个景点的游客情况. H市一共有N个旅游景点(编号1..N),由M条单向游览路线连接.在一个景点游览完后,可以顺着游览线路前往下一个景点. 为了避免游客重复游览同一个景点,游览线路保证是没有环路的. 每一个调查团可以从任意一个景点出发,沿着计划好的游览线路依次调查,到达终点后再返回.每个景点只会有一个调查团经过,不会重复调查. 举个例子: 上图中一共派出了3个调查团: 1

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

UVA 1306 - The K-League(网络流)

UVA 1306 - The K-League 题目链接 题意:n个球队,已经有一些胜负场,现在还有一些场次,你去分配胜负,问每支球队有没有可能获胜 思路:网络流公平分配模型,把场次当作任务,分配给人,然后先贪心,枚举每个人,让这些人能赢的都赢,剩下的去建图,每个源点连向比赛容量为场次,每个比赛连向2个球队,容量无限大,每个球队连向汇点,容量为每个的人的总和减去当前已经赢的,建完图跑一下最大流,然后判断源点流出的是否都满流即可 代码: #include <cstdio> #include &l

hdu 4975 A simple Gaussian elimination problem.(网络流,判断矩阵是否存在)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 Problem Description Dragon is studying math. One day, he drew a table with several rows and columns, randomly wrote numbers on each elements of the table. Then he counted the sum of each row and col

POJ训练计划3422_Kaka&#39;s Matrix Travels(网络流/费用流)

解题报告 题目传送门 题意: 从n×n的矩阵的左上角走到右下角,每次只能向右和向下走,走到一个格子上加上格子的数,可以走k次.问最大的和是多少. 思路: 建图:每个格子掰成两个点,分别叫"出点","入点", 入点到出点间连一个容量1,费用为格子数的边,以及一个容量∞,费用0的边. 同时,一个格子的"出点"向它右.下的格子的"入点"连边,容量∞,费用0. 源点向(0,0)的入点连一个容量K的边,(N-1,N-1)的出点向汇点连一

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

LibreOJ #6002. 「网络流 24 题」最小路径覆盖

内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:Special Judge 上传者: 匿名 网络流 最大流 屠龙宝刀点击就送 #include <cstring> #include <cstdio> #include <queue> #define N 6005 #define inf 0x3f3f3f3f using namespace std; bool flag[N]; int n,m,dep[N],nextt[N<

POJ 1273 Drainage Ditches (网络流Dinic模板)

Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage

网络流(进阶)

最大流:DINIC or SAP 最小费用最大流:SPFA+增广(费用的值较离散) or ZKW(费用的值集中) 有源汇的上下界最大流:新建s', t',用(i, j, l, r)表示i到j有一条下界为l上界为r的边,将每条这样的边拆成(s', j, 0, l), (i, t', 0, l), (i, j, 0, r-l),加入边(t, s, 0, max)再从s'到t'求最大流,再去掉(t, s, 0, max)这条边,从s到t求最大流 有源汇的上下界最小可行流:基本同上,将最后一步改成从t到