zoukankan      html  css  js  c++  java
  • LibreOJ 6002 最小路径覆盖(最大流)

    题解:最小路径覆盖=总点数减去最大匹配数,拆点,按照每条边前一个点连源点,后一个点连汇点跑最大流,即可跑出最大匹配数,然后减一减就可以了~

    代码如下:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x3f3f3f3f
    #define hi puts("hi");
    using namespace std;
    
    int head[100010],next[100010],v[100010],w[100010],deep[100010];
    int s,t,cnt;
    
    void init()
    {
        cnt=-1;
        memset(head,-1,sizeof(head));
        memset(next,-1,sizeof(next));
    }
    
    void add(int from,int to,int cost)
    {
        cnt++;
        next[cnt]=head[from];
        w[cnt]=cost;
        v[cnt]=to;
        head[from]=cnt;
    }
    
    void add_edge(int from,int to,int cost)
    {
        add(from,to,cost);
        add(to,from,0);
    }
    
    int bfs(int s,int t)
    {
        queue<int> q;
        memset(deep,0,sizeof(deep));
        deep[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1; i=next[i])
            {
                if(w[i]>0&&(!deep[v[i]]))
                {
                    deep[v[i]]=deep[u]+1;
                    q.push(v[i]); //
                }
            }
        }
        if(!deep[t])
        {
            return 0;
        }
        return 1;
    }
    
    int dfs(int u,int t,int dist)
    {
        if(u==t)
        {
            return dist;
        }
        for(int i=head[u]; i!=-1; i=next[i])
        {
            if(w[i]&&(deep[v[i]]==deep[u]+1))
            {
                int di=dfs(v[i],t,min(w[i],dist));
                if(di>0)
                {
                    w[i]-=di;
                    w[i^1]+=di;
                    return di;
                }
            }
        }
        return 0;
    }
    
    int dinic(int s,int t)
    {
        int res=0;
        while(bfs(s,t))
        {
            while(int d=dfs(s,t,inf))
            {
                res+=d;
            }
        }
        return res;
    }
    
    int n,m;
    int vis[100010];
    
    int solve(int x,int &f)
    {
        int loc=x+n;
        vis[x]=1;
        for(int i=head[loc];i!=-1;i=next[i])
        {
            if(w[i]==1&&v[i]!=n*2+1)
            {
                solve(v[i],f);
            }
        }
        if(f==1)
        {
            f=0;
        }
        else
        {
            putchar(' ');
        }
        printf("%d",x);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        init();
        s=0;t=n*2+1;
        for(int i=1;i<=n;i++)
        {
            add_edge(s,i,1);
            add_edge(i+n,t,1);
        }
        int x,y;
        while(m--)
        {
            scanf("%d%d",&x,&y);
            add_edge(x,y+n,1);
        }
        int ans=n-dinic(s,t);
        for(int i=head[t];i!=-1;i=next[i])
        {
            if(w[i]==1&&!vis[v[i]-n])
            {
                int f=1;
                solve(v[i]-n,f);
                puts("");
            }
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    B+树的Copy-on-Write设计
    so库链接和运行时选择哪个路径下的库?
    Xapian索引-文档检索过程分析之匹配百分比
    Xapian索引-文档检索过程分析
    Xapian的内存索引-添加文档
    Xapian的内存索引
    Xapian使用入门
    一个std::sort 自定义比较排序函数 crash的分析过程
    编译GCC4.8.2
    使用C++11的一点总结
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/8571350.html
Copyright © 2011-2022 走看看