zoukankan      html  css  js  c++  java
  • poj3020

    无向二分图的最小路径覆盖 = 顶点数 – 最大二分匹配数/2

      1 #include <iostream>
      2 #include <string>
      3 #include <vector>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <map>
      7 #include <algorithm>
      8 #include <list>
      9 #include <ctime>
     10 #include <set>
     11 #include <queue>
     12 #include <cstring>
     13 #include <cstdio>
     14 using namespace std;
     15 #define INT_MAX 10000000
     16 #define N 1005
     17 #define CLR(arr, what) memset(arr, what, sizeof(arr))
     18 int capacity[N][N]; //容量
     19 int flow[N]; //残余流量
     20 int pre[N]; //前趋
     21 int n; //节点个数
     22 
     23 queue<int> Q;
     24 
     25 int BFS(int src, int des) {
     26     //初始化
     27     while (!Q.empty()) {
     28         Q.pop();
     29     }
     30     for (int i = 1; i < n + 1; i++) {
     31         pre[i] = -1;
     32     }
     33     pre[src] = 0;
     34     flow[src] = INT_MAX; //初始化源点的流量为无穷大
     35     Q.push(src);
     36     while (!Q.empty()) {
     37         int index = Q.front();
     38         Q.pop();
     39         if (index == des) { //找到了增广路径
     40             break;
     41         }
     42         for (int i = 1; i < n + 1; i++) {
     43             if (i != src && capacity[index][i] > 0 && pre[i] == -1) {
     44                 pre[i] = index;
     45                 //增广路残容流量
     46                 flow[i] = min(capacity[index][i], flow[index]);
     47                 Q.push(i);
     48             }
     49         }
     50     } //while
     51     if (pre[des] == -1) {
     52         return -1; //残留图中不存在增广路径
     53     } else {
     54         return flow[des];
     55     }
     56 }
     57 
     58 int MaxFlow(int src, int des) {
     59     int aug = 0;
     60     int sumflow = 0;
     61     while ((aug = BFS(src, des)) != -1) {
     62         int k = des; //利用前驱寻找路径
     63         while (k != src) {
     64             int last = pre[k];
     65             capacity[last][k] -= aug;
     66             capacity[k][last] += aug;
     67             k = last;
     68         }
     69         sumflow += aug;
     70     }
     71     return sumflow;
     72 }
     73 struct node {
     74     string in, out;
     75     int cap;
     76 };
     77 int checkin(string & a, string& b) {
     78     int sz = a.size();
     79     bool judge = 1;
     80     for (int i = 0; i < sz; i++) {
     81         if (a[i] == '2' || b[i] == '2') {
     82             continue;
     83         } else if (a[i] != b[i]) {
     84             judge = 0;
     85             break;
     86         }
     87     }
     88     if (1 == judge)
     89         return 1;
     90     return 0;
     91 }
     92 
     93 int cur[N]; //后继
     94 int dis[N]; //距离
     95 int gap[N]; //层结点数(用于间隙优化)
     96 int SAP(int s, int t) //源点、汇点、结点数
     97         {
     98     CLR(gap, 0);
     99     CLR(cur, 0);
    100     CLR(dis, 0);
    101     int u = pre[s] = s, maxflow = 0, aug = INT_MAX;
    102     int v;
    103     gap[0] = n;
    104     while (dis[s] < n) {
    105         bool flag = false;
    106         for (v = cur[u]; v <= n; ++v) //寻找允许弧
    107                 {
    108             if (capacity[u][v] > 0 && dis[u] == dis[v] + 1) {
    109                 flag = true;
    110                 break;
    111             }
    112         }
    113         if (flag) //找到允许弧
    114         {
    115             pre[v] = u;
    116             cur[u] = v;
    117             aug = min(aug, capacity[u][v]);
    118             u = v;
    119             if (v == t) //找到完整增广路
    120                     {
    121                 maxflow += aug;
    122                 for (v = t; v != s; v = pre[v]) //更新残留网络
    123                         {
    124                     capacity[pre[v]][v] -= aug; //正向边
    125                     capacity[v][pre[v]] += aug; //反向边
    126                 }
    127                 aug = INT_MAX;
    128                 u = s; //重新从源点寻找
    129             }
    130         } else //找不到允许弧
    131         {
    132             int mindis = n;
    133             for (v = 1; v <= n; ++v) //重新标号
    134                     {
    135                 if (capacity[u][v] && mindis > dis[v]) {
    136                     cur[u] = v;
    137                     mindis = dis[v];
    138                 }
    139             }
    140             if (--gap[dis[u]] == 0) //更新断层 + 判断是否断层(间隙优化)
    141                 break;
    142             gap[dis[u] = mindis + 1]++; //更新断层
    143             u = pre[u]; //当前弧优化
    144         }
    145     }
    146     return maxflow;
    147 }
    148 
    149 inline void addedge(int x, int y, int c) { // add an arc(x -> y, c); vertex: 0 ~ n-1;
    150     capacity[x][y] = c;
    151 }
    152 int tag[N][N]; //容量
    153 int dx[] = { 1, 0, -1, 0 };
    154 int dy[] = { 0, 1, 0, -1 };
    155 int main() {
    156     int u, v, r, c, itnu;
    157     cin >> itnu;
    158     for (int abc = 0; abc < itnu; abc++) {
    159         CLR(capacity, 0);
    160         CLR(tag, 0);
    161         string tmp;
    162         vector<string> data;
    163         cin >> r >> c;
    164         for (int i = 0; i < r; i++) {
    165             cin >> tmp;
    166             data.push_back(tmp);
    167         }
    168         int node_num = 0;
    169         for (int i = 0; i < r; i++) {
    170             for (int j = 0; j < c; j++) {
    171                 if (data[i][j] == '*') {
    172                     node_num++;
    173                     tag[i][j] = node_num;
    174                 }
    175             }
    176         }
    177         n = node_num * 2 + 2;
    178         for (int i = 0; i < node_num; i++) {
    179             addedge(0, i + 1, 1);
    180             addedge(node_num + i + 1, n - 1, 1);
    181         }
    182         for (int i = 0; i < r; i++) {
    183             for (int j = 0; j < c; j++) {
    184                 if (tag[i][j] != 0) {
    185                     u = tag[i][j];
    186                     for (int a = 0; a < 4; a++) {
    187                         int x = i + dx[a];
    188                         int y = j + dy[a];
    189                         if (x >= 0 && x < r && y >= 0 && y < c) {
    190                             if (tag[x][y] > 0) {
    191                                 v = tag[x][y] + node_num;
    192                                 addedge(u, v, 1);
    193                             }
    194                         }
    195                     }
    196                 }
    197             }
    198         }
    199 //        int sum = MaxFlow(0, n - 1);
    200         int sum = SAP( 0, n - 1);
    201         cout << node_num - sum / 2 << endl;
    202     }
    203     return 0;
    204 }

    from kakamilan

  • 相关阅读:
    Entity Framework使用汇总
    关于大型网站技术演进的思考(二)--存储的瓶颈(中)(转)
    关于大型网站技术演进的思考(一)--存储的瓶颈(上)(转)
    百度十年产品经验总结:产品经理的独孤九剑
    2014年最热门的国人开发开源软件TOP100
    将javadoc附加到eclipse中
    Equals与GetHashcode
    AngularJS学习笔记二
    AngularJS学习笔记一
    Visual Studio无法解析nuget的解决方法
  • 原文地址:https://www.cnblogs.com/kakamilan/p/3072588.html
Copyright © 2011-2022 走看看