题目大意:给出一个有向图,问最多能够分成多少个区域,使得每个区域内的任意一对顶点X、Y间,要么X能达到Y,要么Y能到达X。
不错的题目!
具体做法是这样的,因为强连通分量内部的点肯定能互相到达,因此先缩点;然后问题就转化成了有向无环图的最小路径覆盖问题,因为缩点之后的图上的任意一条路径都是满足要求的。
以下是我的代码:
/*
 * Author:  lee1r
 * Created Time:  2011/8/15 11:04:01
 * File Name: hdu3861.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#define L(x) ((x)<<1)
#define R(x) (((x)<<1)+1)
#define Half(x) ((x)>>1)
#define Lowbit(x) ((x)&(-(x)))
using namespace std;
const int kInf(0x7f7f7f7f);
const double kEps(1e-8);
typedef unsigned int uint;
typedef long long int64;
typedef unsigned long long uint64;
const int kMaxn(5007);
const int kMaxm(100007);
struct Edge
{
    int u,v;
};
int N,M,cnt,first2[kMaxn],next2[kMaxm],e2[kMaxm];
int n,dfscnt,dfsn[kMaxn],low[kMaxn],id[kMaxn];
stack<int> s;
bool instack[kMaxn];
int nx,ny,maxmatch,first[kMaxn],next[kMaxm];Edge e[kMaxm];
int cx[kMaxn],cy[kMaxn],distx[kMaxn],disty[kMaxn];
int head,tail,q[kMaxn];
void Input()
{
    cnt=0;
    memset(first2,-1,sizeof(first2));
    
    scanf("%d%d",&N,&M);
    for(int i=1;i<=M;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        cnt++;
        e2[cnt]=v;
        next2[cnt]=first2[u];
        first2[u]=cnt;
    }
}
void dfs(int u)
{
    dfsn[u]=low[u]=++dfscnt;
    s.push(u);
    instack[u]=true;
    for(int i=first2[u];i!=-1;i=next2[i])
    {
        int v(e2[i]);
        if(!dfsn[v])
        {
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])
            low[u]=min(low[u],dfsn[v]);
    }
    if(dfsn[u]==low[u])
    {
        n++;
        int v;
        do
        {
            v=s.top();s.pop();
            instack[v]=false;
            id[v]=n;
        }while(v!=u);
    }
}
void Tarjan()
{
    n=dfscnt=0;
    memset(dfsn,0,sizeof(dfsn));
    memset(instack,false,sizeof(instack));
    for(int i=1;i<=N;i++)
        if(!dfsn[i])
            dfs(i);
}
void Rebuild()
{
    cnt=0;
    nx=ny=n;
    memset(first,-1,sizeof(first));
    for(int u=1;u<=N;u++)
        for(int i=first2[u];i!=-1;i=next2[i])
        {
            int v(id[e2[i]]);
            if(id[u]==v)
                continue;
            bool found(false);
            for(int j=first[id[u]];j!=-1;j=next[j])
                if(e[j].v==v)
                {
                    found=true;
                    break;
                }
            if(found)
                continue;
            cnt++;
            e[cnt].u=id[u];e[cnt].v=v;
            next[cnt]=first[id[u]];
            first[id[u]]=cnt;
        }
}
bool BFS()
{
    bool re(false);
    head=tail=0;
    memset(distx,0,sizeof(distx));
    memset(disty,0,sizeof(disty));
    for(int i=1;i<=nx;i++)
        if(cx[i]==-1)
            q[tail++]=i;
    while(head!=tail)
    {
        int h,t;
        for(h=head,t=tail;h!=t;h=(h+1)%kMaxn)
        {
            int u(q[h]);
            for(int i=first[u];i!=-1;i=next[i])
            {
                int v(e[i].v);
                if(!disty[v])
                {
                    disty[v]=distx[u]+1;
                    if(cy[v]==-1)
                        re=true;
                    else
                    {
                        distx[cy[v]]=disty[v]+1;
                        q[tail]=cy[v];
                        tail=(tail+1)%kMaxn;
                    }
                }
            }
        }
        head=t;
    }
    return re;
}
bool DFS(int u)
{
    for(int i=first[u];i!=-1;i=next[i])
    {
        int v(e[i].v);
        if(disty[v]==distx[u]+1)
        {
            disty[v]=0;
            if(cy[v]==-1 || DFS(cy[v]))
            {
                cx[u]=v;
                cy[v]=u;
                return true;
            }
        }
    }
    return false;
}
void HopcroftKarp()
{
    maxmatch=0;
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    
    while(BFS())
    {
        for(int i=1;i<=nx;i++)
            if(cx[i]==-1 && DFS(i))
                maxmatch++;
    }
}
void Output()
{
    printf("%d\n",n-maxmatch);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Input();
        Tarjan();
        Rebuild();
        HopcroftKarp();
        Output();
    }
    
    return 0;
}
	posted on 2011-08-17 00:07 
lee1r 阅读(425) 
评论(0)  编辑 收藏 引用  所属分类: 
题目分类:图论