Ordering Tasks UVA - 10305

这题深搜宽搜都有写法,由于是初学我就都试了一遍,各有各的思路吧(个人感觉);

先上深搜写法

#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,那就应该是第二个

依次循环

个人感觉宽搜比较难理解,不过写起来思路清晰;


阅读更多
换一批

没有更多推荐了,返回首页