zoukankan      html  css  js  c++  java
  • 缩点+最小路径覆盖 hdu 3861

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

    题意:输入t,表示t个样例。接下来每个样例第一行有两个数n,m表示点数和有向边的数量,接下来输入m条有向边,现在要我们把点划分成最少的块,每个块里面的点两两之间要至少有一条有向边可以从其中一个点到另一个点。

    思路:分成的区域里面两个点之间至少要有一个点可以到达另一个点,并且要区域数最少,那么就是求最小路径覆盖,但是要求最小路径覆盖的前提是要是无环,所以我们要先用tarjan算法缩点,然后在在缩完点的图上面建一个二分图来求最小路径覆盖。

    最小路径覆盖我是刚刚接触,推荐博客:https://www.cnblogs.com/jianglangcaijin/p/5989907.html

    这里我用的是链式前向星,没有用vector,代码长了一点

    代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<set>
    #include<cstdio>
    #include<string>
    #include<deque> 
    using namespace std;
    typedef long long LL;
    #define eps 1e-8
    #define INF 0x3f3f3f3f
    #define maxn 5005
    struct node{
        int v,next;
    }edge1[maxn*2*10],edge2[maxn*2*10];
    int head1[maxn],dfn[maxn],low[maxn],s[maxn],color[maxn];
    int head2[maxn],pre[maxn*2];
    bool vis[maxn*2];
    int top,cnt1,time,color_num;
    int cnt2,ans;
    int n,m,k,t;
    void init()
    {
        memset(head1,-1,sizeof(head1));
        memset(dfn,0,sizeof(dfn));
        memset(vis,false,sizeof(vis));
        memset(pre,-1,sizeof(pre));
        memset(head2,-1,sizeof(head2));
        cnt1=time=color_num=top=0;
        cnt2=ans=0;
    }
    void addedge1(int u,int v)//第一次建图添加边 
    {
        edge1[++cnt1].v=v;
        edge1[cnt1].next=head1[u];
        head1[u]=cnt1;
    }
    void addedge2(int u,int v)//第二次建图添加边 
    {
        edge2[++cnt2].v=v;
        edge2[cnt2].next=head2[u];
        head2[u]=cnt2;
        
    }
    void DFS(int u)//缩点(染色) 
    {
        low[u]=dfn[u]=++time;
        vis[u]=true;
        s[top++]=u;
        for(int i=head1[u];i!=-1;i=edge1[i].next)
        {
            int v=edge1[i].v;
            if(!dfn[v])
            {
                DFS(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
            low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            color_num++;
            int v;
            do{
                v=s[--top];
                vis[v]=false;
                color[v]=color_num;
            }while(u!=v);
        }
    }
    void tarjan()
    {
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])
            DFS(i);
        }
    }
    void rebuild()
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=head1[i];j!=-1;j=edge1[j].next)
            {
                int v=edge1[j].v;
                int a=color[i];
                int b=color[v];
                if(a!=b)
                addedge2(a,b);//建一个二分图
                //最小路径覆盖就是点数减最大匹配,注意前提是图里面无环,所以要先缩点 
            }
        }
    }
    bool hungry_DFS(int u)//求最大匹配 
    {
        for(int i=head2[u];i!=-1;i=edge2[i].next)
        {
            int v=edge2[i].v;
            if(vis[v])
            continue;
            vis[v]=true;
            if(pre[v]==-1||hungry_DFS(pre[v]))
            {
                pre[v]=u;
                return true;
            }
        }
        return false;
    }
    void hungry()
    {
        for(int i=1;i<=color_num;i++)
        {
            memset(vis,false,sizeof(vis));
            if(hungry_DFS(i))
            ans++;
        }
        printf("%d
    ",color_num-ans);//注意这里是缩点之后的点数减最大匹配数 
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            init();
            int u,v;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&u,&v);
                addedge1(u,v);//第一次建图 
            }
            tarjan();//缩点 
            rebuild();//第二次建图 
            hungry();//求最大匹配 
        }
        return 0;
    }
  • 相关阅读:
    递归算法解析成树形结构
    Tomcat性能参数设置
    hibernate.cfg.xml 配置(摘录)
    OpenCms 集成外部Solr Server
    安装配置OPENCMS的Replication cluster(从)详细过程
    ruby 格式化当前日期时间
    Ruby 语法快速入门
    ruby condition
    配置 RAILS FOR JRUBY1.7.4
    我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(五)框架及Web项目的组件化
  • 原文地址:https://www.cnblogs.com/6262369sss/p/9806631.html
Copyright © 2011-2022 走看看