• Light OJ 1034


    题目链接: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
    ", cases, ans);
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        for(int i=1; i<=t; ++ i)
            solve(i);
        return 0;
    }
  • 相关阅读:
    APICloud学习笔记之图片缓存
    正则表达式笔记01
    hahah
    panel 绑定鼠标滚轮事件
    C#无边框窗体移动 将事件绑定到想实现的控件上
    消消看最高分破解
    字符串补齐
    ant android打包--学习第一弹
    Windsock套接字I/O模型学习 --- 第三章
    Lua 垃圾收集机制
  • 原文地址:https://www.cnblogs.com/aiterator/p/6440391.html
Copyright © 2020-2023  润新知