• Hdu 5352 MZL's City (多重匹配)


    题目链接:

      Hdu 5352 MZL's City

    题目描述:

      有n各节点,m个操作。刚开始的时候节点都是相互独立的,一共有三种操作:

      1:把所有和x在一个连通块内的未重建过的点全部重建。

      2:建立一条双向路(x,y)

      3:又发生了地震,p条路被毁。

      问最后最多有多少个节点被重建,输出重建节点的最小字典序。

    解题思路:

      这几天正好在学匹配,但是昨天下午还是没有看出来这个是匹配题目。看了题解扪心自问了自己三次,是不是傻。就是把每个需要重建的节点x拆成k个点,然后对每个拆分后的点和与拆点在同一连通块里面的点建边,然后按照倒序进行匹配,保证字典序最大。

      但是匹配好像要比网络流慢好多,改天还是去学一下新姿势的好。

      1 #include <vector>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 const int maxn = 205;
      8 const int N = 205*500;
      9 vector <int> G[N];
     10 int ans[maxn*2], p[maxn], used[maxn], vis[maxn];
     11 int n, m, k, num, nu, maps[maxn][maxn];
     12 void dfs (int u)
     13 {//求连通块内的点
     14     vis[u] = 1;
     15     p[num ++] = u;
     16     for (int i=1; i<=n; i++)
     17         if (!vis[i] && maps[u][i])
     18             dfs (i);
     19 }
     20 bool Find (int u)
     21 {
     22     for (int i=0; i<G[u].size(); i++)
     23     {
     24         int v = G[u][i];
     25         if (!vis[v])
     26         {
     27             vis[v] = 1;
     28             if (!used[v] || Find(used[v]))
     29             {
     30                 used[v] = u;
     31                 return true;
     32             }
     33         }
     34     }
     35     return false;
     36 }
     37 int hungry ()
     38 {
     39     int res = 0;
     40     memset (used, 0, sizeof(used));
     41     for (int i=nu-1; i>=0; i--)//倒序求最大匹配
     42         for (int j=i*k; j<(i+1)*k; j++)
     43         {
     44             memset (vis, 0, sizeof(vis));
     45             if (Find(j))
     46             {
     47                 res ++;
     48                 ans[i] ++;
     49             }
     50         }
     51     return res;
     52 }
     53 int main ()
     54 {
     55     int t;
     56     scanf ("%d", &t);
     57     while (t --)
     58     {
     59         scanf ("%d %d %d", &n, &m, &k);
     60         memset (maps, 0, sizeof(maps));
     61         for (int i=0; i<N; i++)
     62             G[i].clear();
     63         nu = 0;
     64         while (m --)
     65         {
     66             int type, x, y, z;
     67             scanf ("%d", &type);
     68             if (type == 1)
     69             {
     70                 scanf ("%d", &x);
     71                 num = 0;
     72                 memset (vis, 0, sizeof(vis));
     73                 dfs (x);
     74                 for (int i=0; i<num; i++)//建边
     75                     for (int j=nu*k; j<(nu+1)*k; j++)//拆点
     76                         G[j].push_back(p[i]);
     77                 nu ++;
     78             }
     79             else if (type == 2)
     80             {
     81                 scanf ("%d %d", &x, &y);
     82                 maps[x][y] = maps[y][x] = 1;
     83             }
     84             else
     85             {
     86                 scanf ("%d", &z);
     87                 while (z --)
     88                 {
     89                     scanf ("%d %d", &x, &y);
     90                     maps[x][y] = maps[y][x] = 0;
     91                 }
     92             }
     93         }
     94         memset (ans, 0, sizeof(ans));
     95         int res = hungry ();
     96         printf ("%d
    ", res);
     97         for (int i=0; i<nu; i++)
     98             printf ("%d%c", ans[i], i==nu-1?'
    ':' ');
     99     }
    100     return 0;
    101 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    AJPFX关于集合的几种变量方式
    AJPFX关于java的依赖 关联 聚合的关系解释
    AJPFX对选择和冒泡两种排序的理解
    AJPFX总结抽象类和接口的区别
    AJPFX的内存管理小结
    AJPFX关于Java内部类及其实例化
    AJPFX总结String类的特点
    AJPFX简述Scanner类的特点
    监督学习——K邻近算法及数字识别实践
    对称(DES/AES)与非对称(RSA/SSL/数字证书)加密介绍及实际应用
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4705202.html
Copyright © 2020-2023  润新知