拓扑排序
拓扑排序
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;
}
浙公网安备 33010602011771号