这题深搜宽搜都有写法,由于是初学我就都试了一遍,各有各的思路吧(个人感觉);
先上深搜写法
#include <iostream>
#include <stdio.h>
#include <queue>
#include <cstring>
#define maxn 10000
using namespace std;
int n,m;
int ans[maxn],ansn=0;
int link[maxn][maxn],vis[maxn];
void dfs(int u)
{
vis[u]=-1;
for(int i=1;i<=n;i++)
{
if(link[u][i])
{
if(vis[i]==-1)return;
else if(!vis[i])
{
dfs(i);
}
}
}
vis[u]=1;
ans[ansn++]=u;
}
int main()
{
while(cin>>n>>m&&n+m!=0)
{
ansn=0;
memset(link,0,sizeof(link));
memset(vis,0,sizeof(vis));
ansn=0;
for(int i=0;i<m;i++)
{
int p,q;
cin>>p>>q;
link[p][q]=1;
}
for(int i=1;i<=n;i++)
{
if(vis[i]!=1)
dfs(i);
}
for(int i=ansn-1;i>=0;i--)
{
cout<<ans[i];
if(i!=0)
cout<<" ";
}
cout<<endl;
}
return 0;
}
深搜的思路是这样的(可以个人画个二叉树试一下):从1开始搜索
如果1后面有数字就在搜索1后面的数字,直到走不通。
然后回溯的时候把路径输出vis标记有两个一个是-1用来判断二叉树的纵向是否有环,就是走没走到过前面的数字,一个是1用来判断二叉树的横向有没有走过
不过深搜输出的不是样例的答案,是多解之一
下面上宽搜:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <cstring>
#define maxn 10000
using namespace std;
int n,m;
int ans[maxn],ansn=0;
int link[maxn][maxn],in[maxn];
void toposort()
{
queue<int>q;
for(int i=1;i<=n;i++)
{
if(in[i]==0)
{
q.push(i);
ans[ansn++]=i;
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
if(link[now][i])
{
in[i]--;
if(in[i]==0)
{
q.push(i);
ans[ansn++]=i;
}
}
}
}
}
int main()
{
while(cin>>n>>m&&n+m!=0)
{
memset(link,0,sizeof(link));
memset(in,0,sizeof(in));
ansn=0;
for(int i=0;i<m;i++)
{
int p,q;
cin>>p>>q;
if(!link[p][q])
{
link[p][q]=1;
in[q]++;
}
}
toposort();
for(int i=0;i<ansn;i++)
{
cout<<ans[i];
if(i!=ansn-1)
cout<<" ";
}
cout<<endl;
}
return 0;
}
宽搜的思路是这样的:
先把入度为0的压入队列,然后把从1到n开始遍历,如果入度为0的下一个入度为1,那就应该是第二个
依次循环
个人感觉宽搜比较难理解,不过写起来思路清晰;