图论题解求有向无环图 互不到达的最大点集的大小

Posted kkkek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论题解求有向无环图 互不到达的最大点集的大小相关的知识,希望对你有一定的参考价值。

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);
    }
}


以上是关于图论题解求有向无环图 互不到达的最大点集的大小的主要内容,如果未能解决你的问题,请参考以下文章

DAG(有向无环图)有向树 转换为树

有向无环图描述表达式(C语言)

有向无环图的哈希值

有向无环图

[CTSC2008]祭祀(二分图+网络流)

有向无环图的判定及拓扑排序