zoukankan      html  css  js  c++  java
  • P2764 最小路径覆盖问题

    P2764 最小路径覆盖问题

    典型的有向无环图求最小路径点覆盖,要求我们选出若干个简单路径,将所有的的点覆盖,且路径之间不能相交,求最少的路径条数...

    我们考虑一个路径覆盖,每个点由于都被覆盖,所以他的入度,出度必然有一个为1.且最大为1.

    我们之后考虑将每个点拆点,分成入度与出度两部分,分到两侧.当有一条边(x,y)时,我们将x的出度连向y的入度.

    路径覆盖中的每条边,在二分图中构成一组匹配,

    考虑每条路径的起点,入度为0,终点,出度为0,分别与入度点,出度点的非匹配点相对应.

    由于求最少的路径覆盖.也就是求最少的起点(终点)->最少的非匹配点)->n-最多的匹配点->n-最大匹配.

    故ADG的最小路径点覆盖=n-拆点二分图的最大匹配.

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=310,M=12010;
    int link[N],tot,n,m,matchx[N],matchy[N],ans;
    bool vis[N];
    struct edge{int y,next;}a[M<<1];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void add(int x,int y)
    {
        a[++tot].y=y;a[tot].next=link[x];link[x]=tot;
    }
    inline bool find(int x)
    {
        for(int i=link[x];i;i=a[i].next)
        {
            int y=a[i].y;
            if(!vis[y])
            {
                vis[y]=1;
                if(!matchy[y]||find(matchy[y])) 
                {
                    matchy[y]=x;
                    matchx[x]=y;
                    return true;
                }
            }
        }
        return false;
    }
    inline void dfs(int x)
    {
        int y=matchx[x]-n;
        if(y<1) return;
        cout<<y<<' ';
        if(!vis[y]&&matchx[y]) vis[y]=1,dfs(y);
    }
    int main()
    {
        freopen("1.in","r",stdin);
        n=read();m=read();
        for(int i=1;i<=m;++i)
        {
            int x=read(),y=read();
            add(x,y+n);
        }
        for(int i=1;i<=n;++i)
        {
            memset(vis,0,sizeof(vis));
            if(find(i)) ans++;
        }
        //for(int i=1;i<=n;++i) cout<<matchx[i]-n<<endl;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;++i)
        {
            if(!vis[i]&&matchx[i]) 
            {
                cout<<i<<' ';
                vis[i]=1;
                dfs(i);
                puts("");
            }
        }
        cout<<n-ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    架构师之路
    责任链设计模式
    Junit框架分析
    线程详解
    课程总结
    IO流
    Java第四次作业
    Character string
    实训
    实训SI
  • 原文地址:https://www.cnblogs.com/gcfer/p/12537287.html
Copyright © 2011-2022 走看看