• 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;
    }

  • 相关阅读:
    按输入行数,输出对应的倒等腰三角形星星
    按输入行、列数,输出对应的矩形星星
    运算程序,计算玩判断,Y继续,重复计算,N结束
    输入年 月 日 ,计算时该年的第几天
    for计算100以内的奇数和
    创建一个Android项目
    菜鸟大充电啦啦啦啦啦:百度上的安卓学习资料以及我的视频学习资料
    菜鸟大充电啦啦啦啦啦:eclipse SDK 是什么啊
    学习过程的记录:实验室电脑上的jdk环境变量
    WHAT is CPU负载?
  • 原文地址:https://www.cnblogs.com/huangdao/p/7726246.html
Copyright © 2020-2023  润新知