拓扑排序

kahn算法

#include <bits/stdc++.h>
const int maxn=100+5,maxm=1e4+5;
struct Node{int to;int next;}e[maxm];
int n,m,len,head[maxn],rd[maxn],a[maxn];
void Insert(int x,int y){
    e[++len].to=y;e[len].next=head[x];head[x]=len;
}
void Kahn(){
    std::stack<int> q;
    for(int i=1;i<=n;++i)//入度为0的点进栈
        if(!rd[i])q.push(i);
    int cnt=0;//计算出栈点的个数
    while(!q.empty()){
        int u=q.top();q.pop();a[++cnt]=u;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;rd[v]--;//相当于删除u的邻接边
            if(!rd[v])q.push(v);
        }
    }
    if(cnt<n){//说明有环
        printf("Cycle\n");return;
    }
    for(int i=1;i<=cnt;++i)
        printf("%d ",a[i]);
}
void Solve(){
    scanf("%d%d",&n,&m);//n个点m条边有向图
    for(int i=1;i<=m;++i){
        int x,y;scanf("%d%d",&x,&y);
        Insert(x,y);rd[y]++;
    }    
    Kahn();
}
int main(){
    Solve();
    return 0;
}

  

基于dfs的算法

#include <bits/stdc++.h>
const int maxn=100+5,maxm=1e4+5;
struct Node{int to;int next;}e[maxm];
int n,m,len,cycle,head[maxn],rd[maxn],vis[maxn];
std::stack<int>q;
void Insert(int x,int y){
    e[++len].to=y;e[len].next=head[x];head[x]=len;
}
void dfs(int u){
	if(cycle==1)return;//如果已经存在环强制退出
	vis[u]=-1;//u设为灰点
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].to;
		if(!vis[v])dfs(v);
		else if(vis[v]==-1){//此时v如果为灰点说明<u,v>是反向边
			printf("Cycle\n");cycle=1;return;
		}//return只能退出一个递归
	}
	vis[u]=1;q.push(u);//u变黑说明无路可走,进栈
}
void Solve(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int x,y;scanf("%d%d",&x,&y);
        Insert(x,y);rd[y]++;
    }    
    for(int i=1;i<=n;++i)//有可能是非连通图
    	if(!rd[i])dfs(i);
    if(cycle==0)//无环则输出拓扑排序
    	while(!q.empty()){
    		printf("%d ",q.top());q.pop();
		}
}
int main(){
    Solve();
    return 0;
}

  

上一篇:蓝桥杯——逗志芃的暴走 (C++)


下一篇:洛谷P6175 无向图的最小环问题