hdu3861

来源:互联网 发布:人工智能 sci期刊 编辑:程序博客网 时间:2024/06/18 16:34
/*
分析:
    把环缩点,求最小路径覆盖。
    果然比赛更激发潜能呀= =,以前很弱的时候见过这个题,
么a掉,今儿个虚拟赛1Y灭之。

                                           2013-05-21
*/








#include"iostream"#include"cstdio"#include"stack"#include"cstring"using namespace std;const int N=5005;const int M=100005;int n,m;int match[N],vis[N];struct Edge{    int u,v,next;}edge[M],edge_n[M];int tot,head[N],tot_n,head_n[N];void add(int a,int b){    edge[tot].u=a;edge[tot].v=b;edge[tot].next=head[a];head[a]=tot++;}void add_n(int a,int b){    edge_n[tot_n].u=a;edge_n[tot_n].v=b;edge_n[tot_n].next=head_n[a];head_n[a]=tot_n++;}//Tarjanint index_s,instack[N],DFN[N],LOW[N],belong[N],cnt;stack<int>st;void Tarjan(int k){    int j,v;    st.push(k);    instack[k]=1;    DFN[k]=LOW[k]=++index_s;    for(j=head[k];j!=-1;j=edge[j].next)    {        v=edge[j].v;        if(instack[v])  LOW[k]=LOW[k]>DFN[v]?DFN[v]:LOW[k];        else if(DFN[v]==-1)        {            Tarjan(v);            LOW[k]=LOW[k]>LOW[v]?LOW[v]:LOW[k];        }    }    if(LOW[k]==DFN[k])    {        do        {            j=st.top();            st.pop();            instack[j]=0;            belong[j]=cnt;        }while(j!=k);        cnt++;    }}void build_new_map(){    int i;    tot_n=0;    memset(head_n,-1,sizeof(head_n));    for(i=0;i<tot;i++)    {        if(belong[edge[i].u]==belong[edge[i].v])    continue;        add_n(belong[edge[i].u],belong[edge[i].v]);    }}void build_map(){    int i;    int a,b;    tot=0;    memset(head,-1,sizeof(head));    for(i=0;i<m;i++)    {        scanf("%d%d",&a,&b);        add(a,b);    }    //缩点    cnt=0;              //这个是新的编号    index_s=0;    memset(DFN,-1,sizeof(DFN));    memset(LOW,-1,sizeof(LOW));    memset(instack,0,sizeof(instack));    for(i=1;i<=n;i++)   belong[i]=i;    for(i=1;i<=n;i++)   if(DFN[i]==-1)  Tarjan(i);    //构造新图    build_new_map();}int dfs(int k){    int j,v;    for(j=head_n[k];j!=-1;j=edge_n[j].next)    {        v=edge_n[j].v;        if(vis[v])  continue;        vis[v]=1;        if(match[v]==-1 || dfs(match[v]))        {            match[v]=k;            return 1;        }    }    return 0;}int main(){    int T;    int i;    cin>>T;    while(T--)    {        scanf("%d%d",&n,&m);        build_map();        int ans=0;        memset(match,-1,sizeof(match));        for(i=0;i<cnt;i++)        {            memset(vis,0,sizeof(vis));            ans+=dfs(i);        }        cout<<cnt-ans<<endl;    }    return 0;}