D01 拓扑排序

D01 拓扑排序_哔哩哔哩_bilibili

B3644 【模板】拓扑排序 / 家谱树 - 洛谷

DAG:有向无环图

1. 入度 in[]==0 的点入队

2. 记录拓扑序

3. 子点入度in[]--,为 0 则入队

// 拓扑排序 Kahn算法 O(V+E)
#include<bits/stdc++.h>
using namespace std;

const int N=110;
int n,in[N];
vector<int> e[N],tp;

bool topo(){
  queue<int> q;
  for(int i=1; i<=n; i++) if(!in[i]) q.push(i);
  while(q.size()){
    int u=q.front(); q.pop();
    tp.push_back(u); //记录拓扑序
    for(auto v:e[u])
      if(--in[v]==0) q.push(v);
  }
  return tp.size()==n;
}
int main(){
  cin>>n;
  for(int i=1,j; i<=n; i++){
    while(cin>>j,j){
      e[i].push_back(j);
      in[j]++; //入度
    }
  }
  topo();
  for(int i=0; i<n; i++) cout<<tp[i]<<" ";
}

 

// 拓扑排序 DFS算法 O(V+E)
#include<bits/stdc++.h>
using namespace std;

const int N=110;
int n,m,a,b;
vector<int> e[N],tp;
int c[N]; //染色数组

bool dfs(int x){
  c[x]=-1;
  for(int y:e[x]){
    if(c[y]<0) return 0; //有环
    else if(!c[y])
      if(!dfs(y)) return 0;
  }
  c[x]=1;
  tp.push_back(x);
  return 1;
 }
bool topo(){
  memset(c,0,sizeof(c));
  for(int x=1; x<=n; x++)
    if(!c[x])
      if(!dfs(x)) return 0;
  reverse(tp.begin(),tp.end());
  return 1;
}
int main(){
  cin>>n;
  for(int i=1,j; i<=n; i++){
    while(cin>>j,j){
      e[i].push_back(j);
    }
  }
  topo();
  for(int i=0; i<n; i++) printf("%d ", tp[i]);
}

 

拓扑排序 - OI Wiki

P1807 最长路 - 洛谷

// 有向无环图的最长路 拓扑排序 O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=1520,M=50010;
int n,m,a,b,c;
vector<pair<int,int>> e[N];
int in[N],d[N];

void topo(){
  memset(d,0x80,sizeof d); //-2139062144
  d[1]=0; d[n]=-1;
  queue<int> q;
  for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
  while(q.size()){
    int u=q.front(); q.pop();
    for(auto [v,w]:e[u]){
      d[v]=max(d[v],d[u]+w);
      if(--in[v]==0) q.push(v);
    }
  }
}
int main(){
  cin>>n>>m;
  for(int i=0;i<m;i++){
    cin>>a>>b>>c;
    e[a].push_back({b,c});
    in[b]++; //入度
  }
  topo();
  cout<<d[n];
}

 

P4017 最大食物链计数 - 洛谷

#include<bits/stdc++.h>
using namespace std;

const int N=5005,p=80112002;
int n,m,x,y,ans;
int in[N],out[N],f[N]; //f[v]走到v点的路径条数
vector<int> e[N];

void topo(){
  queue<int> q;
  for(int i=1;i<=n;i++) if(!in[i]) q.push(i),f[i]=1; //起点赋值1
  while(q.size()){
    int u=q.front(); q.pop();
    if(!out[u]) ans=(ans+f[u])%p; //终点累计答案
    for(int v:e[u]){
      f[v]=(f[v]+f[u])%p;
      if(--in[v]==0) q.push(v);
    }
  }
}
int main(){
  cin>>n>>m;
  for(int i=1;i<=m;i++){
    cin>>x>>y;
    e[x].push_back(y);
    in[y]++; out[x]++;
  }
  topo();
  cout<<ans;
}

 

posted @ 2022-05-28 13:07  董晓  阅读(2214)  评论(0)    收藏  举报