Light OJ 1034 - Hit the Light Switches(强联通分量)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1034

题目大意:有n盏灯,有m个关系, 关系a,b表示如果a灯开关打开那么b灯也会亮起来, 现在求至少需要打开多少开关使所有灯都亮。

题目思路:先由强联通分量缩点, 得到DAG图, 然后根据DAG图,求出有多少入度为0的点, 即为所求。

代码如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 10007;

vector<int>vec[N], stk;
int low[N], dfn[N], belong[N], in[N];
bool mk[N];
int tot, cou_scc;

void tarjan(int u, int f)
{
    dfn[u] = low[u]= tot ++;
    stk.push_back(u), mk[u] = true;
    for(int i=0; i<vec[u].size(); ++ i)
    {
        int v = vec[u][i];
        if(dfn[v] == -1)
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
        }
        else if(mk[v])
        {
            low[u] = min(low[u], dfn[v]);
        }
    }

    if(low[u] == dfn[u])
    {
        ++ cou_scc;
        while(1)
        {
            int v = stk.back();
            stk.pop_back();
            mk[v] = false;
            belong[v] = cou_scc;
            if(u == v)
                break;
        }
    }
}
void solve(int cases)
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; ++ i)
        vec[i].clear();
    int u, v;
    for(int i=1; i<=m; ++ i)
    {
        scanf("%d%d", &u, &v);
        vec[u].push_back(v);
    }
    memset(low, -1, sizeof(low));
    memset(dfn, -1, sizeof(dfn));
    memset(mk, false, sizeof(mk));
    tot = 0, cou_scc = 0;
    for(int i=1; i<=n; ++ i)
    {
        if(dfn[i] == -1)
            tarjan(i, -1);
    }

    memset(in, 0, sizeof(in));
    for(int i=1; i<=n; ++ i)
    {
        for(int j=0; j<vec[i].size(); ++ j)
        {
            int v = vec[i][j];
            if(belong[i] != belong[v])
                in[belong[v]] ++;
        }
    }
    int ans = 0;
    for(int i=1; i<=cou_scc; ++ i)
    {
        if(in[i] == 0)
            ans ++;
    }
    printf("Case %d: %d\n", cases, ans);
}

int main()
{
    int t;
    scanf("%d", &t);
    for(int i=1; i<=t; ++ i)
        solve(i);
    return 0;
}

 

posted @ 2017-02-24 21:30  aiterator  阅读(268)  评论(0编辑  收藏  举报