• POJ 2553 The Bottom of a Graph (强连通分量+缩点)


    题意:给定n个点和他们的有向关系,求出这个有向图中所有的sink点,sink点定义:如果一个点u为sink点,那么他所有能到达的点v,也能有一条通路v->u存在。

    思路:根据sink点的定义,我们很容易想到了强连通分量,但是思考如下情形:如果强连通分支A中有一点u,可以到到强连通分支B中的一点v,由强连通分支定义,v肯定无法到达u,那么A中所有的就不是sink点。所以在求完强联通分支后,还要检验强连通分支之间的关系,只有与其他强联通分支无关的分支中的点才是sink点。此题中求强连通分量用的是前后两边DFS。

    #include <iostream>
    #include
    <cstdio>
    #include
    <algorithm>
    #include
    <memory.h>
    #include
    <cmath>
    #include
    <ctime>
    #include
    <bitset>
    #include
    <queue>
    #include
    <vector>
    using namespace std;

    const int BORDER = (1<<20)-1;
    const int MAXSIZE = 37;
    const int MAXN = 5050;
    const int INF = 1000000000;
    #define CLR(x,y) memset(x,y,sizeof(x))
    #define ADD(x) x=((x+1)&BORDER)
    #define IN(x) scanf("%d",&x)
    #define OUT(x) printf("%d\n",x)
    #define MIN(m,v) (m)<(v)?(m):(v)
    #define MAX(m,v) (m)>(v)?(m):(v)
    #define ABS(x) ((x)>0?(x):-(x))

    typedef
    struct{
    int v,next;
    }Edge;

    Edge edge_r[MAXN
    *MAXN],edge_p[MAXN*MAXN];
    vector
    <int> vet[MAXN];
    int n,m,index_r,index_p,cnt;
    bool visit[MAXN];
    int order[MAXN],net_p[MAXN],net_r[MAXN],set[MAXN];
    bool b_set[MAXN];

    void add_edge(Edge* edge,int* net,int& index,const int& u,const int& v)
    {
    edge[index].v
    = v;
    edge[index].next
    = net[u];
    net[u]
    = index++;
    }
    int init()
    {
    CLR(visit,
    0);
    CLR(order,
    0);
    CLR(net_r,
    -1);
    CLR(net_p,
    -1);
    CLR(
    set,0);
    CLR(b_set,
    0);
    for(int i = 0; i < MAXN; ++i)
    vet[i].clear();
    index_r
    = index_p = 0;
    return 0;
    }
    int input()
    {
    int u,v;
    for(int i = 0; i < m; ++i)
    {
    scanf(
    "%d%d",&u,&v);
    add_edge(edge_p,net_p,index_p,u,v);
    add_edge(edge_r,net_r,index_r,v,u);
    }
    return 0;
    }
    void dfs_p(const int& u)
    {
    visit[u]
    = true;
    for(int i = net_p[u]; i != -1; i = edge_p[i].next)
    if(!visit[edge_p[i].v])
    dfs_p(edge_p[i].v);
    order[
    ++cnt] = u;
    }
    void dfs_r(const int& u)
    {
    visit[u]
    = true;
    set[u] = cnt;
    vet[cnt].push_back(u);
    for(int i = net_r[u]; i != -1; i = edge_r[i].next)
    if(!visit[edge_r[i].v])
    dfs_r(edge_r[i].v);
    }
    void _check()
    {
    int i,j,tmp;
    for(i = 1; i <= n; ++i)
    {
    if(b_set[set[i]] )
    continue;
    for(j = net_p[i]; j != -1; j = edge_p[j].next)
    if(set[i] != set[edge_p[j].v])
    break;
    if(j != -1)
    b_set[
    set[i]] = true;
    }
    }
    int work()
    {
    int i,j,tmp,v,u,ans;
    cnt
    = 0;
    for(i = 1; i <= n; ++i)
    if(!visit[i])
    dfs_p(i);
    CLR(visit,
    0);
    cnt
    = 0;
    for(i = n; i > 0; --i)
    if(!visit[order[i]])
    {
    ++cnt;
    dfs_r(order[i]);
    }
    _check();
    CLR(visit,
    0);
    for(i = 1; i <= cnt; ++i)
    {
    if(b_set[i])
    continue;
    for(j = 0; j < vet[i].size(); ++j)
    visit[vet[i][j]]
    = true;
    }
    int index = 0;
    for(i = 1; i <= n; ++i)
    if(visit[i])
    set[index++] = i;
    if(index == 0)
    printf(
    "\n");
    else
    {
    printf(
    "%d",set[0]);
    for(i = 1; i < index; ++i)
    printf(
    " %d",set[i]);
    printf(
    "\n");
    }
    return 0;
    }
    int main()
    {
    while(IN(n) && n)
    {
    IN(m);
    init();
    input();
    work();
    }
    return 0;
    }

  • 相关阅读:
    邀请函|2021 云原生实战峰会,邀请您免费现场参会报名
    Game On Serverless:SAE 助力广州小迈提升微服务研发效能
    说出你和「云原生」的故事,获得年度云原生顶级盛会通行证
    巧用浏览器F12调试器定位系统前后端bug
    测试人员怎样定位bug原因
    mysql删除某个表前100条数据
    设计模式之工厂方法模式
    2021.11.19
    20211117
    JQuery插件集合
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1722312.html
Copyright © 2020-2023  润新知