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;
    }
    
  • 相关阅读:
    jquery easy ui 学习 (8)basic treegrid
    jquery easy ui 学习 (7) TreeGrid Actions
    jquery easy ui 学习 (6) basic validatebox
    jquery easy ui 学习 (5) windowlayout
    jquery easy ui 学习 (4) window 打开之后 限制操纵后面元素属性
    提示“应用程序无法启动,因为应用程序的并行配置不正确”不能加载 System.Data.SQLite.dll
    visual studio 添加虚线的快捷键
    VS2010打开项目时,出现“已经在解决方案中打开了具有该名称的项目”问题的解决方案
    visual studio 编译时 出现 Files 的值 乱码
    微信 连接被意外关闭
  • 原文地址:https://www.cnblogs.com/-wzd233/p/14042955.html
Copyright © 2011-2022 走看看