hdu6165 FFF at Valentine 强联通缩点

https://vjudge.net/contest/181274#problem/E

自己不集中精力。debug到想哭。。而且一些反例没有想好。。比如
这里写图片描述
只能参考http://blog.youkuaiyun.com/Richie_ll/article/details/77488066

当然还有别的判断方法。。比如看能不能一条路径走完全部点。。
而且暴力的话也是可以的。。用bfs

stack<int>S;
int cost[N];
int uu[N<<1],fst[N],to[N<<1],nxt[N<<1],dfs_clock;
int low[N],pre[N],e;
int sccno[N];
int scc_cnt;
int in[N],out[N];
int n,m;
inline void add(int u,int v,int c){
    uu[e]=u;cost[e]=c;to[e]=v;nxt[e]=fst[u];fst[u]=e++;
}
void dfs(int u){
    low[u]=pre[u]=++dfs_clock;
    S.push(u);
    for(int i=fst[u];~i;i=nxt[i]){
        int v=to[i];
        if(!pre[v]){
            dfs(v);
            low[u]=min(low[v],low[u]);
        }
        else if(!sccno[v]){
            low[u]=min(low[u],pre[v]);
        }
    }
    if(pre[u]==low[u]){
        scc_cnt++;
        while(1){
            int x=S.top();S.pop();
            sccno[x]=scc_cnt;
            if(x==u)break;
        }
    }
}
int vis[N];
bool  solve(){
    int num=0;
    int num1=0;
    int tmp=0;
    mem(vis,0);
    for(int i=1;i<=scc_cnt;++i){
        if(out[i]==0)num++;
        if(in[i]==0)num1++,tmp=i;
    }

    if(num>=2||num1>=2)return false;
    queue<int>q;
    for(int i=1;i<=scc_cnt;++i){
        if(in[i]==0){in[i]--;q.push(i);}
    }
    int flag=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        flag--;
        for(int i=fst[x];~i;i=nxt[i]){
            if(cost[i]==0)continue;
            int v=to[i];
            in[v]--;
            if(in[v]==0){
                flag++;
                in[v]--;
                q.push(v);
            }
            if(flag>=2)return false;
        }
    }
    return true;
}
int main(){
    int T;sf("%d",&T);
    while(T--){
        mem(fst,-1);e=0;scc_cnt=0;
        mem(vis,0);mem(sccno,0);dfs_clock=0;
        mem(out,0);mem(in,0);mem(cost,0);mem(pre,0);mem(low,0);
        sf("%d%d",&n,&m);
        rep(i,1,m){
            int u,v;sf("%d%d",&u,&v);
            add(u,v,0);
        }
        for(int i=1;i<=n;++i){ if(!pre[i])dfs(i); }
        int cnt=0;
        int tmp=e;
        for(int i=0;i<tmp;++i){
            int u=uu[i],v=to[i];
            if(sccno[u]!=sccno[v]){
                add(sccno[u],sccno[v],1);
                out[sccno[u]]++;in[sccno[v]]++;
            }
        }
        if(!solve())puts("Light my fire!");
        else puts("I love you my love and our love save us!");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值