H: Animal Companion in Maze

13 篇文章 0 订阅
7 篇文章 0 订阅

题目来源:
CSUOJ 2298: Animal Companion in Maze
CodeForces Gym101158H Animal Companion in Maze

#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#include <sstream>
#define LL long long
#define LD long double
#define ULL unsigned long long
#define UI unsigned int
#define _for(i,j,k) for(int i=j;i<=k;i++)
#define for_(i,j,k) for(int i=j;i>=k;i--)
#define lowbit(x) (x&-x)
#define ls(x) x<<1
#define rs(x) x<<1|1
//#pragma comment(linker, "/STACK:10240000000,10240000000")
using namespace std;
const int maxn = 1e5+5;
struct E{
    int mkv,u,v;
};
int n,m;
int head[maxn],e[maxn<<2],net[maxn<<2],cnt;
int head2[maxn],net2[maxn<<2],cnt2;
E e2[maxn<<2];
int dfn[maxn],low[maxn],mkr[maxn],df,mk,inq[maxn];
stack<int> st;
queue<int> q;
int ein[maxn],dp[maxn][2],rt[maxn];
void add_edge(int u,int v){
    e[++cnt]=v;
    net[cnt]=head[u];
    head[u]=cnt;
}
void add_edge2(int u,int v){
    e2[++cnt2].mkv=mkr[v];
    e2[cnt2].u=u;
    e2[cnt2].v=v;
    net2[cnt2]=head2[mkr[u]];
    head2[mkr[u]]=cnt2;
}
void tarjan(int u){
    dfn[u]=low[u]=++df;
    st.push(u);
    inq[u]=1;
    for(int i=head[u];i;i=net[i]){
        if(!dfn[e[i]]) tarjan(e[i]);
        if(inq[e[i]]) low[u]=min(low[u],low[e[i]]);
    }
    if(dfn[u]==low[u]){
        mk++;
        while(inq[u]){
            inq[st.top()]=0;
            mkr[st.top()]=mk;
            st.pop();
        }
        rt[mk]=u;
    }
}
bool ck(int u,int pre){
    if(dfn[u]) return false;
    dfn[u]=1;
    for(int i=head[u];i;i=net[i]){
        if(mkr[u]!=mkr[e[i]]||e[i]==pre) continue;
        if(!ck(e[i],u)) return false;
    }
    return true;
}
void dfs1(int u,int pre){//Take the max. of longest distance through children
    for(int i=head[u];i;i=net[i]){
        if(mkr[u]!=mkr[e[i]]||e[i]==pre) continue;
        dfs1(e[i],u);
        if(dp[e[i]][0]+1>dp[u][0]){
            dp[u][1]=dp[u][0];
            dp[u][0]=dp[e[i]][0]+1;
        }
        else dp[u][1]=max(dp[u][1],dp[e[i]][0]+1);
    }
}
void dfs2(int u,int pre){//Propagate the longest distance through parent
    for(int i=head[u];i;i=net[i]){
        if(mkr[u]!=mkr[e[i]]||e[i]==pre) continue;
        if(dp[e[i]][0]+1==dp[u][0]){
            if(dp[u][1]+1>dp[e[i]][0]){
                dp[e[i]][1]=dp[e[i]][0];
                dp[e[i]][0]=dp[u][1]+1;
            }
            else dp[e[i]][1]=max(dp[e[i]][1],dp[u][1]+1);
        }
        else{
            if(dp[u][0]+1>dp[e[i]][0]){
                dp[e[i]][1]=dp[e[i]][0];
                dp[e[i]][0]=dp[u][0]+1;
            }
            else dp[e[i]][1]=max(dp[e[i]][1],dp[u][0]+1);
        }
        dfs2(e[i],u);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    int u,v,w;
    _for(i,1,m){
        cin>>u>>v>>w;
        add_edge(u,v);
        if(w==2) add_edge(v,u);
    }
    _for(i,1,n) if(!dfn[i]) tarjan(i);
    _for(i,1,n) dfn[i]=0;
    _for(i,1,n) if(!dfn[i]&&(!ck(i,i))){
        cout<<"Infinite";
        return 0;
    }
    _for(i,1,n){
        for(int j=head[i];j;j=net[j]){
            if(mkr[i]!=mkr[e[j]]){
                add_edge2(i,e[j]);
                ein[mkr[e[j]]]++;
                //cout<<i<<" "<<e[j]<<" "<<mkr[i]<<" "<<mkr[e[j]]<<endl;
            }
        }
    }
    //cout<<ein[1]<<endl;
    //_for(i,1,mk) cout<<ein[i]<<endl;
    _for(i,1,mk) if(!ein[i]) q.push(i);
    while(!q.empty()){
        u=q.front();q.pop();//cout<<rt[u]<<endl;
        dfs1(rt[u],0);
        dfs2(rt[u],0);
        for(int i=head2[u];i;i=net2[i]){
            ein[e2[i].mkv]--;
            if(!ein[e2[i].mkv]) q.push(e2[i].mkv);
            dp[e2[i].v][0]=max(dp[e2[i].v][0],dp[e2[i].u][0]+1);
        }
    }
    int an=0;
    //_for(i,1,mk) cout<<ein[i]<<endl;
    _for(i,1,n) an=max(an,dp[i][0]);
    //_for(i,1,n) cout<<dp[i][0]<<endl;
    cout<<an;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值