2017多校第9场第5题

图的弱连通。

缩点后,拓补排序。

    #include<cstdio>
    #include<cstring>
    #include<stack>
    using namespace std;

    const int N = 1050;

    struct Edge{
        int s,e,next;
    }edge1[10*N],edge2[10*N];

    int n,m,e_num1,e_num2,vis_num,cnt;
    int head[N],instack[N],low[N],tim[N],belong[N],de[N];

    void AddEdge(int a,int b,Edge edge[],int &e_num){
        edge[e_num].s=a; edge[e_num].e=b; edge[e_num].next=head[a]; head[a]=e_num++;
    }

    void getmap(){
        int a,b;
        scanf("%d%d",&n,&m);
        e_num1=0;
        memset(head,-1,sizeof(head));
        while(m--){
            scanf("%d%d",&a,&b);
            AddEdge(a,b,edge1,e_num1);
        }
    }

    stack <int> st;
    void tarjan(int x){
        int j;
        tim[x]=low[x]=++vis_num;
        instack[x]=1;
        st.push(x);
        for(j=head[x];j!=-1;j=edge1[j].next){
            int u=edge1[j].e;
            if(tim[u]==-1){
                tarjan(u);
                if(low[x]>low[u])low[x]=low[u];
            }
            else if(instack[u] && low[x]>tim[u])low[x]=tim[u];
        }
        if(low[x]==tim[x]){
            cnt++;
            do{
                j=st.top();
                st.pop();
                instack[j]=0;
                belong[j]=cnt;
            }while(j!=x);
        }
    }

    int topo()
    {
        int i,cur,u,count,num;
        count=0;
        for(i=1;i<=cnt;i++){
            if(de[i]==0){
                cur=i;count++;
            }
        }
        if(count>1)return 0;
        num=cnt;
        while(num--){
            count=0;
            for(i=head[cur];i!=-1;i=edge2[i].next){
                u=edge2[i].e;
                de[u]--;
                if(de[u]==0){
                    count++;cur=u;
                }
            }
            if(count>1)return 0;
        }
        return 1;
    }

    void solve(){
        int i;
        cnt=vis_num=0;
        memset(instack,0,sizeof(instack));
        memset(low,0,sizeof(low));
        memset(tim,-1,sizeof(tim));
        for(i=1;i<=n;i++){
            if(tim[i]==-1)tarjan(i);
        }

        e_num2=0;
        memset(head,-1,sizeof(head));
        memset(de,0,sizeof(de));
        for(i=0;i<e_num1;i++){
            int j=edge1[i].s;
            int k=edge1[i].e;
            if(belong[j]!=belong[k]){
                AddEdge(belong[j],belong[k],edge2,e_num2);
                de[belong[k]]++;
            }
        }
        topo()==1?puts("I love you my love and our love save us!"):puts("Light my fire!");
    }

    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            getmap();
            solve();
        }
        return 0;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值