• hdu-4185.loiol_skimming(简单二分匹配模型)


     1 /*************************************************************************
     2     > File Name: hdu-4185.oil_skimming.cpp
     3     > Author: CruelKing
     4     > Mail: 2016586625@qq.com 
     5     > Created Time: 2019年09月03日 星期二 09时12分12秒
     6     本题思路:简单分析过后就可以知道如果一点a被另一个点b匹配,那么和b匹配的点c不可能和点a匹配,因为每个结点都只能匹配四个方向,所以这个匹配的图就可以看做是一个二分图,因此对于每个结点,将能和他匹配的边存入,接着跑一波二分匹配之后我们得到的是无向图情况下的最大匹配,所以除以二就是最后的答案.
     7  ************************************************************************/
     8 
     9 #include <cstdio>
    10 #include <cstring>
    11 #include <cmath>
    12 using namespace std;
    13 
    14 const int maxn = 600 + 5;
    15 char str[maxn][maxn];
    16 
    17 int n;
    18 int linker[maxn * maxn];
    19 bool used[maxn * maxn];
    20 int tot, head[maxn * maxn];
    21 int un[maxn * maxn], cnt;
    22 
    23 struct Edge {
    24     int to, next;
    25 } edge[maxn * maxn * 4 + 5];
    26 
    27 void init() {
    28     memset(head, -1, sizeof head);
    29     tot = 0;
    30 }
    31 
    32 void addedge(int u, int v) {
    33     edge[tot] = (Edge) {v, head[u]};
    34     head[u] = tot ++;
    35 }
    36 
    37 bool dfs(int u) {
    38     for(int k = head[u]; ~k; k = edge[k].next) {
    39         int v = edge[k].to;
    40         if(!used[v]) {
    41             used[v] = true;
    42             if(linker[v] == -1 || dfs(linker[v])) {
    43                 linker[v] = u;
    44                 return true;
    45             }
    46         }
    47     }
    48     return false;
    49 }
    50 
    51 int main() {
    52     int k, Case = 0;
    53     scanf("%d", &k);
    54     while(k --) {
    55         init();
    56         cnt = 0;
    57         scanf("%d", &n);
    58         for(int i = 0; i < n; i ++) {
    59             scanf("%s", str[i]);
    60         }
    61         for(int i = 0; i < n; i ++) {
    62             for(int j = 0; j < n; j ++) {
    63                 if(str[i][j] == '#') {
    64                     un[cnt ++] = (i * n + j + 1);
    65                     for(int dx = -1; dx <= 1; dx ++) {                    
    66                         for(int dy = -1; dy <= 1; dy ++) {                        
    67                             if(abs(dx - dy) == 1) {        
    68                                 if(dx + i >= 0 && dx + i < n && dy + j >= 0 && dy + j < n) {                    
    69                                     if(str[dx + i][dy + j] == '#') addedge(i * n + j + 1, (i + dx) * n + j + dy + 1);
    70                                 }
    71                             }
    72                         }
    73                     }
    74                 }
    75             }
    76         }
    77         int res = 0;
    78         memset(linker, -1, sizeof linker);
    79         for(int i = 0; i < cnt; i ++) {
    80             memset(used, false, sizeof used);
    81             if(dfs(un[i])) res ++;
    82         }
    83         printf("Case %d: %d
    ", ++Case, res / 2);
    84     }
    85     return 0;
      }
  • 相关阅读:
    时区处理
    C#视频取帧图
    【C#】C#获取文件夹下的所有文件
    利用web of science做论文综述
    C# HTML解析工具HtmlAgilityPack使用实例(一)
    C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)
    win10文件夹或文件已在另一程序中打开
    指定网卡IP进行ping操作
    C# 使用WebClient时,在多网卡IP时,指定IP发送Web请求
    C# 消息队列
  • 原文地址:https://www.cnblogs.com/bianjunting/p/11453537.html
Copyright © 2020-2023  润新知