hdu 3861 强连通分量缩点+二分匹配求最小路径覆盖

来源:互联网 发布:java数组末尾添加元素 编辑:程序博客网 时间:2024/05/16 06:31
//用tarjan求出强连通分量,再将强连通分量的所有点缩为一个点
//具体的tarjan算法http://www.cnblogs.com/saltless/archive/2010/11/08/1871430.html
//然后重新建图,很容易想到剩下的是一个最小路径覆盖的题目
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 50100;
int low[maxn];
int dfn[maxn];
int vis[maxn];
int stack[maxn];
int instack[maxn];
int match[maxn];
int belong[maxn];
int top,step,num;
vector<int> vec_1[maxn];
vector<int> vec_2[maxn];
int dx[maxn*2],dy[2*maxn];
int n ,m;
void init()
{
    step = top = num = 0;
    memset(instack,0,sizeof(instack));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    for(int i = 0;i <= n;i++)
    {
        vec_1[i].clear();
        vec_2[i].clear();
    }
}
void tarjan(int  u)
{
    stack[++top] = u;
    instack[u] = 1;
    low[u] = dfn[u] = ++step;
    for(int i = 0; i < vec_1[u].size() ;i++)
    {
        int v= vec_1[u][i];
        if(!dfn[v])
        {
            tarjan(v) ;
            low[u] = min(low[u],low[v]);
        }
        else if(instack[v])
        low[u] = min(low[u],dfn[v]);
    }
    if(low[u] == dfn[u])
    {
        num ++;
        int v = 0 ;
        while(u!=v)
        {
            v = stack[top--];
            belong[v] = num;
            instack[v] = 0;
        }
    }
}
int find(int start)
{
    for(int i = 0;i < vec_2[start].size();i++)
    {
        int v = vec_2[start][i];
        if(!vis[v])
        {
            vis[v] = 1;
            if(match[v] == -1 || find(match[v]))
            {
                match[v] = start;
                return 1;
            }
        }
    }
    return 0;
}
void Match()
{
    memset(match, -1,sizeof(match));
    int ans = 0;
    for(int i = 1;i <= num ;i++)
    {
        memset(vis,0,sizeof(vis));
        if(find(i))
        ans++;
    }
    printf("%d\n",num - ans);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int  i = 1;i <= m ;i++)
        {
            scanf("%d%d",&dx[i] ,&dy[i]);
            vec_1[dx[i]].push_back(dy[i]);
        }
        for(int i = 1;i <= n;i++)
        if(!dfn[i])
        tarjan(i);
        for(int i = 1;i <= m;i++)
        {
            int u = belong[dx[i]];
            int v = belong[dy[i]];
            if(u == v)continue;
            vec_2[u].push_back(v);
        }
        Match();
    }
    return 0;
}

































































0 0
原创粉丝点击