zoukankan      html  css  js  c++  java
  • 洛谷P3183 [HAOI2016]食物链

    (dp)太菜了,紧急补课。就从入门题开始吧。。。

    思路

    其实这题我第一眼是没想到(dp)的,一下就看出是拓扑排序后简单递推了(递推也算(dp)吧。。。),切了。然后考虑到自己不会记忆化搜索,所以才学一波。

    “记搜好就好在可以自动找出拓扑序”————zhx

    那么既然这题可以用拓扑排序做,当然也就可以使用记搜。其实在递归入门题斐波那契数列的优化中就使用过记搜,用数组记录这个数有没有递归过,如果递归过直接返回值就好了。好像也把这题做完了。但是代码实现还是有一些细节的,而且我也终于理解了为什么记搜不用找拓扑序。因为就算不是按照拓扑序搜的,搜完之后,当搜到起点的时候,由于它后面的点已经搜完了,所以直接返回数组就行了,也就相当于是从起点开始按照拓扑序搜的了。

    代码(剽窃后自己打了一遍)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N=100005,M=200005;
    int n,m,tot,ans;
    int ver[M],Next[M],head[N],f[N],in[N],out[N];
    void add(int x,int y){
    	ver[++tot]=y;
    	Next[tot]=head[x];
    	head[x]=tot;
    }
    int dfs(int x){
    	if(f[x]) return f[x];//记搜的精髓所在,不然就和爆搜没区别了
    	int sum=0;//sum用来统计从这个点出发能到达终点的路径条数
    	if(out[x]==0) return 1;//如果到达了终点,那么返回1,说明可以到达
    	for(int i=head[x];i;i=Next[i]){
    		sum+=dfs(ver[i]);//路径条数累加
    	}
    	f[x]=sum;//f[x]记录从点x出发能到达终点的路径条数
    	return sum;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1,x,y;i<=m;i++){
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		in[y]++;
    		out[x]++;
    	}
    	for(int i=1;i<=n;i++){
    		if(in[i]==0&&out[i]!=0){
    			ans+=dfs(i);
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    eclipse 10个常用 快捷键
    struts2 s:set标签
    web项目的路径问题
    linux系统中用户切换
    java的多线程(一)
    Mongodb 与 Mongoose 的使用
    escape()、encodeURI()、encodeURIComponent()区别详解
    JSON WEB TOKEN
    关于使用REST API
    mac下设置mongodb开机启动方法
  • 原文地址:https://www.cnblogs.com/57xmz/p/13907222.html
Copyright © 2011-2022 走看看