zoukankan      html  css  js  c++  java
  • 拓扑排序(topo sort)之 最大食物链计数( 洛谷P4017)

    前言:
    复习复习拓扑排序,自己把自己弄没了/kk
    题目传送门
    简化题意:
    在一个DAG中,求从所有入度为0的点到所有出度为0的点路径的条数
    md理解错题意把自己卡了半天,生物学的好的就可以直接理解为求食物链的数目就OK了
    只要不和我一样以为是求最长链的个数就不会有大问题
    不跟我一样傻乎乎的求最长路计数就没问题
    看到DAG , 看到入度为0 ,出度为0,脑子就自然跳出一个东西 拓扑排序 这个东西单独考的还是蛮少的,就我目前知识点来看,这个和强联通分量联系是最多的,毕竟缩完点后的DAG你不会写了你可以用topo打暴力(O(n+m)) SPFA 玄学复杂度
    拓扑排序其实没啥可以讲的,这个东西原理很简单

    • 每次找到入度为0的点让它进队列
    • 当队列不为空,取出队首,遍历它所能到达的所有点,然后把这两个点之间的边删去如果遍历到的点的入度变成 0 了,这个点入队
    • 重复以上过程,完事(遍历过程中你想干啥干啥)

    回归本题,这个题可以通过tupo来解决到每一个出度为 0 的点有几条路线
    $dp[from] = dp[fomr] + dp[to] $ 每一个入度为0的点初始化(dp[x] = 1)
    最后可以加每一个出度为0的点的dp值就可以得到答案
    (ans =sum dp_i | i in cd[i]=0)

    The Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    using namespace std;
    const int N = 5e5+100;
    const int mod = 80112002;
    int read(){
    	int s = 0 ,f = 1; char ch = getchar();
    	while(ch < '0'||ch > '9'){if(ch == '-') f = -1 ; ch = getchar();}
    	while(ch >= '0'&&ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * f;
    }
    struct node{
    	int from, to, dis , next;
    }e[N << 1];
    struct Queue{
    	int a[N] , head = 1 ,tail = 0;
    	void Push(int x){  a[++tail] = x;return ; }
    	void Pop(){ head++; }
    	bool Empty(){ return head > tail;}
    	int Front(){ return a[head];} 
    }q;
    int rd[N],cd[N],dp[N];
    int head[N] , nume;
    void add_edge(int from, int to){
    	e[++nume].to = to ,e[nume].next = head[from] , head[from] = nume;
    }
    void tupo(){
    	while(!q.Empty()){
    		int fr = q.Front();
    		//cout<<fr<<" ";
    		q.Pop();
    		for(int i = head[fr] ; i ; i = e[i].next){
    			int to = e[i].to;
    			rd[to]--;
    			dp[to] = (dp[fr] + dp[to]) % mod ;
    			if(rd[to] == 0) q.Push(to);
    		}
    	}
    }
    int main(){
    	int n = read() , m = read();
    	for(int i = 1 ,u ,v ; i <= m ;i++){
    		u = read() , v = read() ;
    		add_edge( u, v) ;
    		rd[v]++,cd[u]++;
    	}
    	for(int i = 1 ; i <= n ;i++){
    		if(rd[i] == 0) q.Push(i),dp[i] = 1;
    	}
    	tupo();
    	int ans = 0;
    	for(int i = 1 ; i <= n ;i++)
    		if(!cd[i]) 
    		ans =(ans+dp[i]) % mod;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    BZOJ3847 : ZCC loves march
    BZOJ3828 : [Poi2014]Criminals
    BZOJ3834 : [Poi2014]Solar Panels
    BZOJ3831 : [Poi2014]Little Bird
    BZOJ3829 : [Poi2014]FarmCraft
    BZOJ2757 : [SCOI2012]Blinker的仰慕者
    BZOJ2707 : [SDOI2012]走迷宫
    给iOS工程增加Daily Build
    给NSString增加Java风格的方法
    象写程序一样写博客:搭建基于github的博客
  • 原文地址:https://www.cnblogs.com/-wzd233/p/14042955.html
Copyright © 2011-2022 走看看