upc 3795 食物链(邻接表+记忆dfs)

来源:互联网 发布:手机知乎怎么复制 编辑:程序博客网 时间:2024/05/22 15:49

题意: 给你食物链 求总条数;

题解:将关系用邻接表储存,因为关系并不稠密,而较分散,用数组不够大,记忆搜过的点避免再次搜索,最后相加,邻接表的建立与搜索直接套模板,只需要考虑下记忆与返回的ans位置,还有记录点的dp数组;


#include <iostream>#include <algorithm> #include <string.h>using namespace std;int m,n;int out[100010],in[100010],vis[100010],dp[100010];struct  point{  //用结构体来实现邻接表 更方便     int from;    int to;    int next;};point pt[200010];int dfs(int x){    int va,i;    if (vis[x]==1)    {        return dp[x]; //如果该点被访问过 直接返回该点下面的条数 不用继续搜索;     }    vis[x]=1;    if (out[x]==0)    {    dp[x]=1;    return 1;    }    int ans=0;    for (i=pt[x].from;i!=-1;i=pt[i].next) //搜索模板     {          va=pt[i].to;         ans+=dfs(va);    }    dp[x]=ans;    return ans;}int main(){    int u,v,sum;    memset(pt,0,sizeof(pt));    memset(out,0,sizeof(out));    memset(in,0,sizeof(in));    memset(vis,0,sizeof(vis));    memset(dp,0,sizeof(dp));    sum=0;    cin>>n>>m;    for (int i=1;i<=n;i++) //初始化 (相当于初始化first数组)     pt[i].from=-1;    for (int i=1;i<=m;i++) //建立邻接表 并记录每个节点的入度与出度     {        cin>>u>>v;        out[u]++;        in[v]++;        pt[i].next=pt[u].from;        pt[i].to=v;        pt[u].from=i;    }    for (int i=1;i<=n;i++)    {        if (in[i]==0&&out[i]!=0) //将每个根节点 (食物链的开端)遍历         sum+=dfs(i);        }     printf("%d\n",sum);    return 0;}