拓扑排序

拓扑排序

https://www.acwing.com/problem/content/850/

	#include<stdio.h>
	#include<algorithm>
	#include<cstring>
	#include<queue>
	#include<iostream>
	using namespace std;
	const int N=1e5+10;
	int ver[N],head[N],net[N],edge[N],tot,n,m,cnt=1;//cnt就是记录用的
	int d[N],a[N];//d[]表示的是每个点的入度
	queue<int>q;
	void add(int x,int y)
	{
	    ver[++tot]=y,net[tot]=head[x],head[x]=tot,d[y]++;//吧有向边添加到数组里
	}
	void topsort()//拓扑排序的模板吧
	{
	    for(int i=1;i<=n;i++)
	    if(!d[i])q.push(i);//先找到入度为0的直接添加
	    while(q.size())
	    {
	        int x=q.front();q.pop();
	        a[cnt++]=x;//记录拓扑排序出来的结果
	        for(int j=head[x];j;j=net[j]){//遍历相邻的边
	            int y=ver[j];
	            if(--d[y]==0) q.push(y);
	            
	        }
	    
	    }
	}
	int main()
	{
	    cin>>n>>m;
	    for(int i=1;i<=m;i++)
	    {
	        int x,y;
	        cin>>x>>y;
	        add(x,y);
	    }
	    topsort();
	    if(cnt==n+1)//如果所有的点都遍历了一遍 就是没有环
	    for(int i=1;i<=n;i++)
	    printf("%d ",a[i]);
	    else
	    printf("-1");
	    return 0;
	}

可达性统计 自己这个点通过下一个节点或者自己这个点可以到达的点的个数

https://www.acwing.com/problem/content/166/

	#include<iostream>
	#include<algorithm>
	#include<stdio.h>
	#include<cstring>
	#include<bitset> 
	#include<queue>
	using namespace std;
	int n, m;
	const int N = 3e4 + 10;
	int cnt;
	int ver[N], tot, head[N], edge[N], Next[N];
	queue<int>q;
	int d[N], a[N];//d存的是每个点的入度 a存的是拓扑排序的顺序
	bitset<N>f[N];//规定了一个 存储的数长度为N的二进制数 的数组
	void add(int x, int y)
	{
		ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
	}
	void calc() {
		for (int j = cnt; j; j--)//把点从后往前遍历一遍
		{
			int x = a[j];
			f[x][x] = 1;//自己可以到自己这个点 也算
			for (int i = head[x]; i; i = Next[i])
			{
				int y = ver[i];//下一条边
				f[x] |= f[y];//按位于上以后 就是我这个点自己能走到的点的个数+另一个点能走到的 就是最终 我这个能走到的
			}
	
	
		}
	
	
	}
	void topsort(){
		
		for (int i = 1; i <= n; i++)
			if (d[i] == 0)
				q.push(i);
		while (q.size()) {
			int x = q.front();
			a[++cnt] = x;//把这个点先加进去
			q.pop();
			for (int i = head[x]; i; i = Next[i])
			{
				int j = ver[i];
				if (--d[j] == 0)
					q.push(j);
			}
	
		}
	}
	
	int main() {
		cin >> n >> m;
		for (int i = 1; i <= m; i++) {
			int x, y;
			cin >> x >> y;
			add(x, y);
			d[y]++;
		}
		topsort();
		calc();
		for (int i = 1; i <= n; i++)
			cout << f[i].count() << endl;//f[].count() 输出的是N的二进制数中 1的个数
		return 0;
	
	
	}

家谱树 没有用queue这个容器 用数组模拟的queue

https://www.acwing.com/problem/content/1193/

	#include<iostream>
	#include<algorithm>
	#include<stdio.h>
	#include<cstring>
	using namespace std;
	int n,m;
	const int N=110,M=N*N/2;
	int idx,e[M],ne[M],h[N];
	int q[N];
	int d[N];
	void add(int x,int y)
	{
		e[idx]=y,ne[idx]=h[x],h[x]=idx++;
	}
	void topsort(){
		int hh=0,tt=-1;//队头和队尾
		for(int i=1;i<=n;i++)
		if(!d[i]) q[++tt]=i;
		while(hh<=tt)
		{
			int t=q[hh++];//把对头取出来
			for(int i=h[t];~i;i=ne[i])//遍历
			{
				int j=e[i];
				 if(--d[j]==0)
				 q[++tt]=j;//加到队尾
			}
		}
		
		
		
		
	}
	int main(){
		cin>>n;
		memset(h,-1,sizeof(h));
		for(int i=1;i<=n;i++){
			int son;
			while(cin>>son,son)
			{
				add(i,son);
				d[son]++;
			}	
		}
		
	topsort();
	for(int i=0;i<n;i++)
	printf("%d ",q[i]);
	return 0;
			
	} 
posted @ 2020-04-16 20:50  arbor_one  阅读(113)  评论(0)    收藏  举报