• HDU 3861 The King’s Problem(强连通分量+最小路径覆盖)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861

    题目大意:

    在csdn王国里面, 国王有一个新的问题. 这里有N个城市M条单行路,为了让他的王国更加高效,国王想要将他的王国划分成几个州,
    每个城市必须属于一个州。对于两个城市(u,v),如果有一条从u到v的路,也有一条从v到u的路,那么u、v必须属于同一个州。
    对于每一个州里的任何两个城市u、v,都有不经过其他州的路从u到v或从v到u。现在国王想要知道他的王国最少可以划分成多少个州。

    解题思路:

    因为“能相互到达的点必须属于同一个州”所以先用强连通分量缩点。然后就是求最小路径覆盖了,思路很清晰,但我没想出来。。。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<stack>
    using namespace std;
    const int N=5e3+5;
    
    int n,m,cnt,num,uN;
    int dfn[N],low[N],fa[N],link[N];
    bool vis[N];
    stack<int>sk;
    vector<int>v[N];
    vector<int>g[N];
    
    void tarjan(int u){
        dfn[u]=low[u]=++cnt;
        sk.push(u);
        for(int i=0;i<v[u].size();i++){
            int t=v[u][i];
            if(!dfn[t]){                                        //点t未被访问
                tarjan(t);
                low[u]=min(low[u],low[t]);
            }
            else if(!fa[t])  low[u]=min(low[u],dfn[t]);         //点t已被访问,且t还在栈中
        }
        if(low[u]==dfn[u]){
            num++;
            while(1){
                int t=sk.top();
                sk.pop();
                fa[t]=num;                                      //缩点操作,将这些点都归为点num
                if(t==u) break;
            }
        }
    }
    
    bool dfs(int u){
        for(int i=0;i<g[u].size();i++){
            int t=g[u][i];
            if(!vis[t]){
                vis[t]=true;
                if(link[t]==-1||dfs(link[t])){
                    link[t]=u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int max_match(){
        memset(link,-1,sizeof(link));
        int ans=0;
        for(int i=1;i<=uN;i++){
            memset(vis,false,sizeof(vis));
            if(dfs(i)) ans++;
        }
        return ans;
    }
    
    void init(){
        cnt=num=0;
        memset(fa,0,sizeof(fa));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        for(int i=0;i<=n;i++){
            v[i].clear();
            g[i].clear();
        }
    }
    
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                v[a].push_back(b);
            }
            for(int i=1;i<=n;i++){
                if(!dfn[i]) tarjan(i);
            }
            //缩点建新图
            for(int i=1;i<=n;i++){
                for(int j=0;j<v[i].size();j++){
                    int t=v[i][j];
                    if(fa[t]!=fa[i]) g[fa[t]].push_back(fa[i]);
                }
            }
            uN=num;
            printf("%d
    ",num-max_match());
        }
        return 0;
    }
  • 相关阅读:
    day10
    day 09
    day08
    day07
    day6
    day5
    成员变量和局部变量
    (第五章)java面向对象之this的作用总结
    简单的音乐播放
    异步消息处理机制 简析
  • 原文地址:https://www.cnblogs.com/fu3638/p/8785489.html
Copyright © 2020-2023  润新知