zoukankan      html  css  js  c++  java
  • 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 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    词汇小助手V1.0——一款跨平台词频统计和外语学习工具
    穿越狙击V1.0
    词汇小助手V1.4——加入单词测试功能
    词汇小助手V1.2——可以显示英语单词的国际音标
    词汇小助手官方网站发布了
    强大的云存储与应用管理工具DzzOffice1.0 Beta(大桌子办公)发布下载 大桌子
    <!DOCTYPE>前加有<! xxx >注释在IE中引发的bug
    去笔试腾讯的前端实习生,题目太尼玛坑爹了
    IE中的布局BUG和一些可以避开的BUG
    removeClass,addClass的原生JS代码
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4705202.html
Copyright © 2011-2022 走看看