#某咸鱼红红火火恍恍惚惚练记忆化搜索的日记
这道题其实和滑雪(SHOI2002)本质是一样的。。
所以现已加入记忆化搜索练习套餐√
思路是dfs,开个数组存搜过的,然后瞎暴力就可以了
但是注意可能会有独立出来的点和图,所以要统计入度和出度
遇到入度为零的需要新一波dfs,遇到入度出度都为零的单点也要记为一条链
破程序:
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN=100003,MAXM=200003;
struct node{
int from,to;
};
int n,m,cnt,ans=0;
int f[MAXN],ru[MAXN],chu[MAXN],head[MAXM];
node map[MAXM*2];
void add(int x,int y) //邻接表加边
{
map[++cnt].from=head[x];
map[cnt].to=y;
head[x]=cnt;
}
int r() //读入优化
{
int f=1,p=0;
char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
p=p*10+c-'0';
c=getchar();
}
return f*p;
}
int dfs(int u) //想写dps...
{
if(f[u]) return f[u];
int ans=0;
if(!chu[u]&&ru[u]) return 1;
for(int i=head[u];i;i=map[i].from)
{
int next=map[i].to;
ans+=dfs(next);
}
f[u]=ans;
return ans;
}
int main()
{
n=r();m=r();
for(int i=1;i<=m;i++)
{
int a,b;
a=r();b=r();
add(a,b);
chu[a]++;ru[b]++; //计入度和出度
}
for(int i=1;i<=n;i++)
{
if(!ru[i]) //找到新的一块r啦
ans+=dfs(i);
}
cout<<ans; //完成w
return 0;
}
最后,一个挺傻白甜的dps格式?
int dps(int x)
{
if(f[x]) return x;
int t=0; //不一定从0开始,反正能做到通过递归计数就好
for()
{
t+=dps();
}
f[x]=t;
return t;
}
(菜到没眼看.jpg)