hdu1269迷宫城堡(tanjar)

哇!
tanjar模板题,但是看懂还是花了一下午…
哎,萌新杀手,要是有个现在的我能给早上的我讲讲,不知道会省去多少时间
targan是干嘛的???
它是找环的
在这里插入图片描述
问:是否任意两个点之间都联通(整个图有且只有一个大环,环包括所有点)

tanjar是dfs搜索,用***时间戳***编号(dfn),并且对于每个点,(low)编号记下的是这个点和下一个点low的最小值,最小值初始化是编号,而后面的编号明显大于前面的,那么low永远等于dfn,直到…
直到它碰到它的信仰啊!
如果它碰到一个访问过的点,那么这个点的dfn是比它的low(dfn)小的,这几个点形成一个环,把这个环上所有点取出来,用这个环为所欲为,做自己想做的事,美滋滋;
targan可以找出所有环。。。嘛,不错的算法

#include <bits/stdc++.h>
using namespace std;
const int maxn=10010;
vector<int> vec[maxn];
int dfn[maxn],low[maxn],vis[maxn],blg[maxn],s[maxn];
//dfn时间戳,low成环的话环上的最小编号,vis判断是否成环,
//blg判断是否只有一个环且包括所有点,s-stack模拟栈
int n,m;int cnt,num,top;
void dfs(int u){
    s[++top]=u;//入栈
    vis[u]=1;int siz=vec[u].size();
    low[u]=dfn[u]=++cnt;int i;//编号
    for(i=0;i<siz;i++){
        int v=vec[u][i];//取出有边点
        if(!dfn[v]){   //如果没编号过,递归
            dfs(v);    
            low[u]=min(low[u],low[v]);   //如果找到了环,赋值环上最小编号
        }else{
            if(vis[v]){
                low[u]=min(low[u],dfn[v]);   //找到环
            }
        }
    }int x;
    if(low[u]==dfn[u]){    //如果自身low=自身dfn,那么是环的最小编号
  					       //(只有一个节点的环也是环)
        num++;
        do{
            x=s[top--];
            vis[x]=0;           //这个很重要可别忘了哦
            blg[x]=num;
        }while(x!=u);           //对整个环,做自己想做的事,这里编号啦
    }
}
void tarjan(){
    int i;
    for(i=1;i<=n;i++){
        if(!dfn[i]){
            dfs(i);
        }
    }
    for(i=1;i<=n;i++){
        if(blg[i]!=num){
            cout<<"No"<<endl;
            return;
        }
    }
    cout<<"Yes"<<endl;
}
int main(){
    int i,j,k;int a,b;
    while(cin>>n>>m,n+m){
        top=0;cnt=0;num=0;
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(vis,0,sizeof vis);
        memset(blg,0,sizeof blg);
        for(i=0;i<=n;i++)vec[i].clear();
        for(i=1;i<=m;i++){
            cin>>a>>b;vec[a].push_back(b);
        }
        tarjan();
    }
}

跨年快乐!!!我爱你们!!!嘿嘿

努力,加油,我要成为最强的acmer(辣鸡快洗洗睡吧)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值