zoukankan      html  css  js  c++  java
  • HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=3861

    题意:

    国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意两个城市u,v,有从u到v的路径或从v到u的路径。求最少可以分成几个州。

    思路:

    这道题目挺好。

    首先,强连通分量进行缩点,重新建图。

    新建的图就是一个DAG图,接下来就转换成了最小路径覆盖问题。

    最小路径覆盖就是用尽量少的不相交的简单路径覆盖DAG的所有顶点。每个顶点只属于一条路径,单个顶点也可以作为一条路径。

    最小路径覆盖=结点总数-最大匹配。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<queue>
      7 #include<cmath>
      8 #include<stack>
      9 using namespace std;
     10 
     11 const int maxn=5000+5;
     12 
     13 int n,m;
     14 
     15 vector<int> G[maxn];
     16 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
     17 stack<int> S;
     18 
     19 vector<int> new_G[maxn];
     20 int vis[maxn];
     21 int match[maxn];
     22 
     23 void dfs(int u) {
     24     pre[u] = lowlink[u] = ++dfs_clock;
     25     S.push(u);
     26     for (int i = 0; i < G[u].size(); i++)
     27     {
     28         int v = G[u][i];
     29         if (!pre[v])
     30         {
     31             dfs(v);
     32             lowlink[u] = min(lowlink[u], lowlink[v]);
     33         }
     34         else if(!sccno[v])
     35         lowlink[u] = min(lowlink[u], pre[v]);
     36     }
     37     if (pre[u] == lowlink[u])
     38     {
     39         scc_cnt++;
     40         for(;;)
     41         {
     42             int x = S.top(); S.pop();
     43             sccno[x] = scc_cnt;
     44             if (x == u) break;
     45         }
     46     }
     47 }
     48 
     49 void find_scc(int n)
     50 {
     51     dfs_clock = scc_cnt = 0;
     52     memset(pre, 0, sizeof(pre));
     53     memset(sccno, 0, sizeof(sccno));
     54     for (int i = 1; i <= n; i++)
     55         if (!pre[i]) dfs(i);
     56 }
     57 
     58 
     59 int match_dfs(int x)
     60 {
     61     for(int i=0;i<new_G[x].size();i++)
     62     {
     63         int v=new_G[x][i];
     64         if(!vis[v])
     65         {
     66             vis[v]=1;
     67             if(match[v]==-1 || match_dfs(match[v]))
     68             {
     69                 match[v]=x;
     70                 return 1;
     71             }
     72         }
     73     }
     74     return 0;
     75 }
     76 
     77 int main()
     78 {
     79     //freopen("D:\input.txt","r",stdin);
     80     int T;
     81     scanf("%d",&T);
     82     while(T--)
     83     {
     84         scanf("%d%d",&n,&m);
     85         for(int i=1;i<=n;i++)  G[i].clear();
     86         while(m--)
     87         {
     88             int u,v;
     89             scanf("%d%d",&u,&v);
     90             G[u].push_back(v);
     91         }
     92         find_scc(n);
     93         for(int i=1;i<=scc_cnt;i++)  new_G[i].clear();
     94         for(int u=1;u<=n;u++)
     95         {
     96             for(int i=0;i<G[u].size();i++)
     97             {
     98                 int v=G[u][i];
     99                 if(sccno[u]!=sccno[v])  new_G[sccno[u]].push_back(sccno[v]);
    100             }
    101         }
    102 
    103         int tot=0;
    104         memset(match,-1,sizeof(match));
    105         for(int i=1;i<=scc_cnt;i++)
    106         {
    107             memset(vis,0,sizeof(vis));
    108             tot+=match_dfs(i);
    109         }
    110 
    111         printf("%d
    ",scc_cnt-tot);
    112     }
    113     return 0;
    114 }
     
  • 相关阅读:
    PWA渐进式增强WEB应用
    如何去掉wordpress头部<link rel='next' href='*/page/2' />
    wordpress修改邮箱提示There is a pending change of your email to
    使用WP-China-Yes让你的wordpress告别429错误
    Focus
    α_β_γ_δ_ε_ζ_η_θ_ι_κ_λ_μ_ν怎么读
    Ubuntu总结常用命令记录
    声明
    你所不知道的冰冷的经济真相(转自来自天涯大佬)
    杨振宁演讲谈这件事:我很高兴中国政府没有上当
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6817075.html
Copyright © 2011-2022 走看看