zoukankan      html  css  js  c++  java
  • hdu6165(拓扑排序+tarjan缩点)

    题意:就任意两个点能否到达;

    解题思路:首先将图简化,比如假设图里有一个环,那么,这环内两个点肯定是能相互到达的,那么就不用考虑这环内的点了,很简单就想到用tarjan算法将环缩成一个点,然后就是判断缩完点后的图内任意两点能否互相到达了,能互相到达一定是有路径连接所有点的,就通过拓扑排序了,如果同一层的两点或以上的入度在排序时都为0时那么肯定不能到达,因为没有路径连接这两个点,这道题属于模板型的题,只要思路正确,是能写出来的,貌似还有暴力dfs的写法,还没去看;

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<queue>
    using namespace std;
    const int MAXN=2e5+5;
    const int MAXM=5e5+5;
    int head[MAXN],tot;
    int low[MAXN],dfn[MAXN],sta[MAXN],bel[MAXN];//bel数组的值是1~scc
    int index,top;
    int scc;//强连通分量的个数
    bool instack[MAXN];
    int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
    //num数组不一定需要,结合实际情况
    int n,m;

    struct Edge
    {
        int from,to,nxt;
    }edge[MAXM];

    void addedge(int u,int v)
    {
        edge[tot].from=u;
        edge[tot].to=v;
        edge[tot].nxt=head[u];
        head[u]=tot++;
    }//链式前向星存图;

    void tarjan(int u)
    {
        int v;
        low[u]=dfn[u]=++index;
        sta[top++]=u;
        instack[u]=true;
        for(int i=head[u];i!=-1;i=edge[i].nxt)
        {
            v=edge[i].to;
            if(!dfn[v])
            {
                tarjan(v);
                if(low[u]>low[v]) low[u]=low[v];
            }else if(instack[v]&&low[u]>dfn[v])
            low[u]=dfn[v];
        }
        if(low[u]==dfn[u])
        {
            scc++;
            do
            {
                v=sta[--top];
                instack[v]=false;
                bel[v]=scc;
                num[scc]++;
            }while(v!=u);
        }
    }//tarjan算法算强联通图;

    void solve(int n)
    {
        memset(dfn,0,sizeof(dfn));
        memset(instack,false,sizeof(instack));
        memset(num,0,sizeof(num));
        index=scc=top=0;
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i]) tarjan(i);
        }
    }

    void init()
    {
        tot=0;
        memset(head,-1,sizeof(head));
    }

    int in[MAXN];
    vector<int> G[MAXN];
    void suodian()
    {
        memset(in,0,sizeof(in));
        for(int i=1;i<=scc;i++) G[i].clear();
        for(int i=0;i<m;i++)
        {
            int u=bel[edge[i].from];
            int v=bel[edge[i].to];
            if(u!=v)
            {
                G[u].push_back(v);
                in[v]++;
            }
        }
        int cnt=0,p;
        for(int i=1;i<=scc;i++)
        {
            if(in[i]==0) {cnt++;p=i;}
        }
        if(cnt>=2) printf("Light my fire! ");
        else
        {
            queue<int> q;
            while(!q.empty()) q.pop();
            q.push(p);
            bool flag=true;
            while(!q.empty())
            {
                int fs=q.front();
                q.pop();
                int du=0;
                int sz=G[fs].size();
                for(int i=0;i<sz;i++)
                {
                    int to=G[fs][i];
                    in[to]--;
                    if(in[to]==0)
                    {
                        du++;
                        q.push(to);
                    }
                }
                if(du>=2) {flag=false;break;}
            }
            if(flag) printf("I love you my love and our love save us! ");
            else printf("Light my fire! ");
        }
    }//缩点后的拓扑排序;

    int main()
    {

        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            init();
            int u,v;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&u,&v);
                addedge(u,v);
            }
            solve(n);
    // cout<<scc<<endl;
    // for(int i=1;i<=n;i++)
    // {
    // cout<<bel[i]<<endl;
    // }
    // cout<<num[1]<<" "<<num[2]<<endl;
            suodian();
        }
        return 0;
    }

  • 相关阅读:
    JS中的继承(上)
    一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends
    JS 装饰器,一篇就够
    理解 JavaScript 的 async/await
    JS正则表达式入门,看这篇就够了
    JavaScript的几种循环方式
    全解跨域请求处理办法
    下班后的时间精力生活管理办法(时间管理)
    hexo上部署博客到Github失败
    11
  • 原文地址:https://www.cnblogs.com/huangdao/p/7726246.html
Copyright © 2011-2022 走看看