zoukankan      html  css  js  c++  java
  • 【图论】【题解】求有向无环图 互不到达的最大点集的大小

    1,ICPC Pacific Northwest Regional Contest 2019 -I

    求给定的无向图,互不到达的点集的大小。(nle500)
    (ans=n-) 最大二分图匹配数目

    (code:)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+5;
    const int inf=0x3f3f3f3f;
    
    void read(int&x)
    {
        char c;
        while(!isdigit(c=getchar()));x=c-'0';
        while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-'0';
    }
    char s[505][30];
    vector<int>p[505];
    int match[505];
    bool vis[505];
    int dfs(int u)
    {
        for(int v:p[u])
        {
            if(vis[v])continue;
            vis[v]=1;
            if(!match[v]||dfs(match[v]))
            {
                match[v]=u;
                match[u]=v;
                return 1;
            }
        }
        return 0;
    }
    int main()
    {
        int n;
        read(n);
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]);
        int len=strlen(s[1]),t;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                t=0;
                for(int k=0;k<len;k++)
                    if(s[i][k]!=s[j][k])t++;
                if(t==2)
                {
                    p[i].push_back(j);
                    p[j].push_back(i);
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof vis);
            vis[i]=1;
            if(!match[i]&&dfs(i))ans++;
        }
        printf("%d
    ",n-ans);
    }
    

    2,ACM_ICPC 2017 Asia Nanning -M

    求给定的有向无环图,互不到达的最大点集的大小。
    (Tle500,\,nle100,\,mle n*(n-1)/2,;sum mle500000)

    做法:对每个点与其能到达的点连边,得到一个新的有向图,对这个有向图求最大二分图匹配,答案则为 (n)-最大二分图匹配数。
    注意有向图和无向图二分匹配的区别:无向图二分匹配后结果 每个点最多只能有一个匹配边,有向图二分匹配结果,每个点最多能有一条指向外的匹配边和指向自己的匹配边(即出度入度各位1).

    (code:)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+5;
    const int inf=0x3f3f3f3f;
    
    void read(int&x)
    {
        char c;
        while(!isdigit(c=getchar()));x=c-'0';
        while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-'0';
    }
    
    vector<int>p[105];
    int out[105],in[105];
    bool vis[105];
    bool dfs(int u)
    {
        for(int v:p[u])
        {
            if(vis[v])continue;
            vis[v]=1;
            if(!in[v]||dfs(in[v]))
            {
                in[v]=u;
                out[u]=v;
                return 1;
            }
        }
        return 0;
    }
    bool eg[105][105];
    int main()
    {
        int T;
        read(T);
        while(T--)
        {
            int n,m,u,v;
            read(n);read(m);
            memset(eg,0,sizeof(eg));
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            for(int i=1;i<=n;i++)p[i].clear();
            for(int i=1;i<=m;i++)
            {
                read(u);read(v);
                eg[u][v]=1;
            }
            for(int k=1;k<=n;k++)
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        if(eg[i][k]&&eg[k][j])eg[i][j]=1;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(i!=j&&eg[i][j])p[i].push_back(j);
            int tn=0;
            for(int i=1;i<=n;i++)
            {
                memset(vis,0,sizeof vis);
                if(!out[i]&&dfs(i))tn++;
            }
            printf("%d
    ",n-tn);
        }
    }
    
  • 相关阅读:
    jackson自动将东八区时间转成标准时间
    开发项目和所用时间 感想
    自我介绍
    后缀数组模板
    lucas模板
    后缀数组da3模板
    cf#366....
    第1月2周1天
    第1月2周2天
    第1月1周1天
  • 原文地址:https://www.cnblogs.com/kkkek/p/12933540.html
Copyright © 2011-2022 走看看