UVA-11504 - Dominos(有向图的强连通分量)

这题就是用有向图的强连通分量来写,然后缩点,再找出入度为0的点的个数,就是答案

注意:不知道为啥要动态分配内存...不这样就RE....郁闷

// File Name: 11504.cpp
// Author: Zlbing
// Created Time: 2013/3/29 14:00:14

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
const int MAXN=1e5+10;
//vector<int> G[MAXN];
struct node{
    int u,v,next;
}*Edge;
int head[MAXN];
int n,m;
int lowlink[MAXN],sccno[MAXN],pre[MAXN];
int scc_cnt,dfs_clock;
stack<int> S;
int k;
void add(int u,int v){
    Edge[k].u = u;
    Edge[k].v = v;
    Edge[k].next = head[u];
    head[u] = k++;
}

void dfs(int u)
{
    pre[u]=lowlink[u]=++dfs_clock;
    S.push(u);
    for(int i=head[u];i!=-1;i=Edge[i].next)
    {
        int v=Edge[i].v;
        if(!pre[v])
        {
            dfs(v);
            lowlink[u]=min(lowlink[u],lowlink[v]);
        }else if(!sccno[v])
        {
            lowlink[u]=min(lowlink[u],pre[v]);
        }
    }
    if(lowlink[u]==pre[u])
    {
        scc_cnt++;
        for(;;){
        int t=S.top();S.pop();
        sccno[t]=scc_cnt;
        if(t==u)break;
        }
    }
}
void find_scc(){
    memset(sccno,0,sizeof(sccno));
    memset(lowlink,0,sizeof(lowlink));
    memset(pre,0,sizeof(pre));
    dfs_clock=0,scc_cnt=0;
    for(int i=1;i<=n;i++)
        if(!pre[i])dfs(i);
}
int in[MAXN];

int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        //CL(G,0);
        CL(head,-1);
        k=0;
        Edge=new node[m+5];
        REP(i,1,m)
        {
            int a,b;
            scanf("%d%d",&a,&b);
        //    G[a].push_back(b);
            add(a,b);
        }
        find_scc();
        CL(in,0);
//        REP(i,1,n)
//        {
//            for(int j=0;j<G[i].size();j++)
//            {
//                int v=G[i][j];
//                if(sccno[i]!=sccno[v])
//                {
//                    in[sccno[v]]++;
//                }
//            }
//        }
        for(int i=0;i<k;i++)
        {
            int s=sccno[Edge[i].u];
            int e=sccno[Edge[i].v];
            if(s!=e)
                in[e]++;
        }
        int ans=0;
        REP(i,1,scc_cnt)
            if(!in[i])ans++;
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-03-29 15:43  z.arbitrary  阅读(522)  评论(0编辑  收藏  举报