前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于判环

关于判环

作者头像
用户2965768
发布2019-06-15 11:09:29
3100
发布2019-06-15 11:09:29
举报
文章被收录于专栏:wymwym

关于有向图的判环

1.只有正(负)边权

拓扑排序一遍就好了

记住,图不一定是联通时,一定要把每个入度为零的节点跑一遍!!!

核心代码如下:

代码语言:javascript
复制
int in[N],timeq=0,n,m;//timeq 时间戳 
int vis[N];//标记数组 
inline bool dfs(int u){//u 当前节点 
    bool flag=false;//flag 标记 
    for(int i=head[u];i;i=e[i].next){//领接表遍历图 
        int v=e[i].to;
        if(timeq==vis[v]) return true;//当前边是返祖边,则有环 
        else if(vis[v]) return false;//上次遍历过了且不是这次遍历产生的,一定没有环 
        flag=dfs(v);//遍历 
        if(flag) return true;
    }
    return false;
}
int main(){
    scanf("%d%d",&n,&m);//n 节点数  m 边数 
    for(int i=1;i<=m;i++){
        int x,y,val;
        scanf("%d%d%d",&x,&y,&val);// x->y的边权值为val 
        add(x,y,val);//邻接表存边 
        in[y]++;//统计入度 
    }
    for(int i=1;i<=n;i++)//顺次访问入度为0的节点 
        if(!in[i]){
            vis[i]=++timeq;//标记访问次数
            if(dfs(i)){//遍历 
                printf("Yes");//有环 
                return 0;
            }
        }
    printf("No");//无环 
} 

2.既有正权边又有负权边

这时,我们就要用SPFA(此处所讲的是dfs版),其实可以用堆优化,但是作者懒,在这不想写

其实也么什么好讲的,主要看毒瘤出题人有没有给重边和自环代码实现

下面的代码包含处理重边和自环的情况:

代码语言:javascript
复制
#include<stdio.h>
#define N 2007
using namespace std;
#define INF 0x3f3f3f3f
struct E{
    int next,to,dis;
}e[N<<2];
int head[N],cnt=0,n,m,dis[N],st;
bool vis[N];
inline void read(int &x){
    x=0;int flag=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') flag=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
    x*=flag;
}
inline void add(int id,int to,int dis){//存图 
    cnt++;
    e[cnt].next=head[id];
    e[cnt].to=to;
    e[cnt].dis=dis;
    head[id]=cnt;
}
inline bool dfs(int u){
    vis[u]=true;//标记已访问过 
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(u==v&&e[i].dis<0) return true;//如果是自环且dis小于0,此环定是负环 
        if(dis[v]>dis[u]+e[i].dis){//更新 
            if(vis[v]) return true;//如果访问过且这次又更新了,一定有负环 
            dis[v]=dis[u]+e[i].dis;
            if(dfs(v)) return true;//往下遍历 
        }
    }
    vis[u]=false;//回溯 
    return false;//返回没有环 
}
int main(){
    read(n);read(m);read(st);//st 源点 
    for(int i=1;i<=n;i++) 
        dis[i]=INF,vis[i]=false;//初始化 dis 到源点的最短路距离 vis 标记数组
    for(int i=1;i<=m;i++){
        int x,y,dis;
        read(x);read(y);read(dis);
        add(x,y,dis);
    }
    dis[st]=0;//初始源点到自身距离为0 
    bool flag=dfs(st);
    if(flag) printf("Yes\n");
    else printf("No\n");
}

关于无向图的判环

无向图就更简单了

直接遍历一遍,如果遇到返祖边则判断一下当前记录的dis[u]+e[i].dis是否为负

如果是,则一定有负环,否则当前没有负环,回溯

其余情况直接往下遍历就是了,没有过多技巧,这里就不再赘述

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于有向图的判环
    • 1.只有正(负)边权
      • 2.既有正权边又有负权边
      • 关于无向图的判环
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档