• LOJ6002—最小路径覆盖


    传送门

    一道比较友好的网络流?的题了吧

    把每个点看做leftileft_i,rightiright_i两个点

    如果两个点之间有一条有向边

    那就把left向right连一条边

    然后做二分图匹配

    答案就是总点数减去匹配数

    但关键是如何证明这样是正确的

    显然最开始的时候每个点是一个独立的集合

    每次我们连一条有向边

    就相当于把两个点匹配在一起,也就把集合数减少了一个了

    那最后集合数就是答案了

    #include<bits/stdc++.h>
    using namespace std;
    int adj[606],nxt[10005],to[10005],lf[10005],rt[10005],vis[10005],ans[10005],cnt,ecnt,n,m;
    inline int read(){
        char ch=getchar();
        int res=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return res;
    }
    inline void addedge(int u,int v){
        nxt[++cnt]=adj[u];adj[u]=cnt,to[cnt]=v;
    }
    inline int dfs(int u){
        for(int e=adj[u];e;e=nxt[e]){
            int v=to[e];
            if(vis[v]) continue;
            vis[v]=1;
            if(lf[v]==-1||dfs(lf[v])){
                lf[v]=u,rt[u]=v;
                return true;
            }
        }
        return false;
    }
    int main(){
        memset(lf,-1,sizeof(lf));
        n=read(),m=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            addedge(u+n,v);
        }
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof(vis));
            dfs(i+n);
        }
        for(int i=1;i<=n;i++){
            if(lf[i]==-1){
                ecnt++;
                cout<<i<<" ";
                int u=i+n;
                while(rt[u]){
                    cout<<rt[u]<<" ";
                    u=n+rt[u];
                }
                cout<<'
    ';
            }
        }        
        cout<<ecnt<<'
    ';
    }
    
  • 相关阅读:
    SQL查询Profile设置
    AP如何定义发票的行分配账户的默认值
    使用UTL_MAIL包实现存储过程邮件发送(转)
    如何优化库存管理
    VS2008 一个IDE配色方案
    Rails2的部分新特性
    TDD Tip:方法内部New出来的对象如何Mock
    我的2008
    rails2.2 无法加载mysql的解决
    ASP.NET MVC AJAX的调用
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366482.html
Copyright © 2020-2023  润新知