• bzoj1143


    最小路径覆盖:有向图的最小路径覆盖为选取最少的路径(路径不相交)能够把图的所有顶点都覆盖(定点不可被重复覆盖)

    做法:将有向图变为拆点二分图,然后进行二分图匹配,答案即为n-|最大匹配数|

    最小路径可重点覆盖:即路径可相交的路径覆盖

    做法:将有向图进行传递闭包后,再进行最小路径覆盖

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    struct my{
           int v;
           int next;
    };
    
    const int maxn=800+10;
    
    int tu[maxn][maxn],fa;
    int adj[maxn*2],match[maxn*2];
    bool vis[maxn*2];
    my bian[maxn*100];
    
    void myinsert(int u,int v){
         bian[++fa].v=v;
         bian[fa].next=adj[u];
         adj[u]=fa;
    }
    
    int dfs(int x){
        for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
            if(!vis[v]){
                vis[v]=true;
                if(!match[v]||dfs(match[v])){
                    match[v]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main(){
        int n,m;
        int u,v;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            tu[u][v]=1;
        }
        for (int i=1;i<=n;i++) tu[i][i]=1;
     for (int k=1;k<=n;k++){
        for (int i=1;i<=n;i++){
            for (int j=1;j<=n;j++){
                tu[i][j] |= tu[i][k] && tu[k][j];
            }
        }
     }
     for (int i=1;i<=n;i++) tu[i][i]=0;
        for (int i=1;i<=n;i++){
            for (int j=1;j<=n;j++){
                if(tu[i][j]) myinsert(i,j+n);
            }
        }
        int ans=n;
        for (int i=1;i<=2*n;i++){
            for (int j=1;j<=2*n;j++) vis[j]=0;
            if(dfs(i)) ans--;
        }
        printf("%d
    ",ans);
    return 0;
    }

    输出方案

    即为一直在路径上找到无有向边相连的点

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    struct my{
           int v;
           int next;
    };
    
    const int maxn=800+10;
    
    int tu[maxn][maxn],fa;
    int adj[maxn*2],match[maxn*2],hide[maxn],vis2[maxn];
    bool vis[maxn*2],succ[maxn*2];
    my bian[maxn*100];
    
    void myinsert(int u,int v){
         bian[++fa].v=v;
         bian[fa].next=adj[u];
         adj[u]=fa;
    }
    
    int dfs(int x){
        for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
            if(!vis[v]){
                vis[v]=true;
                if(!match[v]||dfs(match[v])){
                    match[v]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main(){
        int n,m;
        int u,v;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            tu[u][v]=1;
        }
        for (int i=1;i<=n;i++) tu[i][i]=1;
     for (int k=1;k<=n;k++){
        for (int i=1;i<=n;i++){
            for (int j=1;j<=n;j++){
                tu[i][j] |= tu[i][k] && tu[k][j];
            }
        }
     }
     for (int i=1;i<=n;i++) tu[i][i]=0;
        for (int i=1;i<=n;i++){
            for (int j=1;j<=n;j++){
                if(tu[i][j]) myinsert(i,j+n);
            }
        }
        int ans=n;
        for (int i=1;i<=2*n;i++){
            for (int j=1;j<=2*n;j++) vis[j]=0;
            if(dfs(i)) ans--;
        }
        int top=0;
        printf("%d
    ",ans);
        for (int i=1;i<=n;i++) succ[match[i]]=true;
        for (int i=1;i<=n;i++) if(!succ[i]) hide[++top]=i;
        bool flag=true;
        while(flag){
            flag=false;
            for (int i=1;i<=ans;i++){
                for (int j=1;j<=n;j++){
                    if(tu[hide[i]][j]) vis2[j]=true;
                }
            }
            for (int i=1;i<=ans;i++){
                if(vis2[hide[i]]){
                    flag=true;
                    while(vis[hide[i]]) hide[i]=match[hide[i]];
                }
            }
        }
        for (int i=1;i<=ans;i++) printf("%d ",hide[i]);
    return 0;
    }
  • 相关阅读:
    图片不能显示
    Lambda表达式where过滤数据
    存储文本到一个文件里
    获取用户临时文件夹路径
    判断某一个字符串是否存在另一个字符串中
    使用反射为特性赋值
    字符串与数据流之间的转换
    控制台应用程序获取计算机名
    重复输出字符或字符串
    使用HashSet<>去除重复元素的集合
  • 原文地址:https://www.cnblogs.com/lmjer/p/9380884.html
Copyright © 2020-2023  润新知