(搜索专题)可达性统计 拓扑排序(DAG有向无环图)链式前向星

链式前向星

struct edge{
    int next;//第i条边同起点的下一条边的存储位置
    int to;//第i条边的终点
    int w;//边权值
};
void add(int u, int v, int w){
    edge[cnt].w = w;
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

拓扑排序

struct node{
    int next;
    int to;
    int w;
}edge[25005];
int head[25005],cnt=0;
void add(int u,int v){
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int indegree[200005],a[200005],n,m,s;

void toposort(){
    queue<int>q;
    for(int i=1;i<=n;i++)
        if(indegree[i]==0)//第i个顶点的入度为0
            q.push(i);
    while(!q.empty()){
        int t=q.front();//第i个顶点拿出来
        q.pop();
        a[s++]=t;//j记录路径
        for(int i=head[t];~i;i=edge[i].next){
            indegree[edge[i].to]--;
            if(indegree[edge[i].to]==0)
                q.push(edge[i].to);
        }
    }
}

int main()
{
    memset(indegree,0,sizeof(indegree));
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    int t,x,y;
    for(int i=0;i<m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
        indegree[y]++;
    }
    s=0;
    toposort();
    for(int i=0;i<s;i++)
    	printf("%d ",a[i]);
    return 0;
}

题目:
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。N,M≤30000。

题解:看到有向无环图,想到拓扑排序

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e4+10;
struct Edge{
    int next;
    int to;
    int w;
}edge[maxn];
int head[maxn];
int a[maxn];
int cnt = 0, tot = 0;
int n, m;
bitset <maxn> s[maxn];
int indegree[maxn];
int copyinde[maxn];
void add(int u, int v){
    edge[++cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}
void toposort(){
    queue<int> q;
    for(int i = 1; i <= n; i++){
        if(indegree[i] == 0)
            q.push(i);
    }
    while(!q.empty()){
        int t = q.front();
        q.pop();
        a[++tot] = t;
        for(int i = head[t]; ~i; i = edge[i].next){
            indegree[edge[i].to]--;
            if(indegree[edge[i].to] == 0)
                q.push(edge[i].to);
        }
    }

}
int main(){

    scanf("%d%d", &n, &m);
    memset(head, -1, sizeof(head));
    int x, y;
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &x, &y);
        add(x, y);
        indegree[y]++;
       // copyinde[y]++;
    }
    toposort();
   for(int i = tot; i >= 1; i--) {
        int x = a[i];
        s[x][x] = 1;
        for(int j=head[x]; j; j = edge[j].next) {
            int to=edge[j].to;
            s[x] |= s[to];
        }
    }
    for(int i = 1; i <= n; i++) printf("%d\n",s[i].count());

return 0;
}

猜你喜欢

转载自blog.csdn.net/eternityZZing/article/details/83473348