Faulty Robot (dfs)两种不同的写法

Faulty Robot

As part of a CS course, Alice just finished programming her robot to explore a graph having nn nodes, labeled 1,2,…,n1,2,…,n, and mm directed edges. Initially the robot starts at node 11.

While nodes may have several outgoing edges, Alice programmed the robot so that any node may have a forced move to a specific one of its neighbors. For example, it may be that node 55 has outgoing edges to neighbors 11, 44, and 66 but that Alice programs the robot so that if it leaves 55 it must go to neighbor 44.

If operating correctly, the robot will always follow forced moves away from a node, and if reaching a node that does not have a forced move, the robot stops. Unfortunately, the robot is a bit buggy, and it might violate those rules and move to a randomly chosen neighbor of a node (whether or not there had been a designated forced move from that node). However, such a bug will occur at most once (and might never happen).

Alice is having trouble debugging the robot, and would like your help to determine what are the possible nodes where the robot could stop and not move again.

We consider two sample graphs, as given in Figures 1 and 2. In these figures, a red arrow indicate an edge corresponding to a forced move, while black arrows indicate edges to other neighbors. The circle around a node is red if it is a possible stopping node.

\includegraphics[width=0.6\textwidth ]{faulty}

Figure 1: First sample graph.

\includegraphics[width=0.3\textwidth ]{faulty2}

Figure 2: Second sample graph.

In the first example, the robot will cycle forever through nodes 11, 55, and 44 if it does not make a buggy move. A bug could cause it to jump from 11 to 22, but that would be the only buggy move, and so it would never move on from there. It might also jump from 55 to 66 and then have a forced move to end at 77.

In the second example, there are no forced moves, so the robot would stay at 11without any buggy moves. It might also make a buggy move from 11 to either 22 or 33, after which it would stop.

Input

The first line contains two integers nn and mm, designating the number of nodes and number of edges such that 1≤n≤1031≤n≤103, 0≤m≤1040≤m≤104. The next mm lines will each have two integers aa and bb, 1≤|a|,b≤n1≤|a|,b≤n and |a|≠b|a|≠b. If a>0a>0, there is a directed edge between nodes aa and bb that is not forced. If aa < 0, then there is a forced directed edge from −a−a to bb. There will be at most 900900 such forced moves. No two directed edges will be the same. No two starting nodes for forced moves will be the same.

Output

Display the number of nodes at which the robot might come to a rest.

Sample Input 1 Sample Output 1
7 9
1 2
2 3
-1 5
2 6
5 1
-4 1
5 6
-6 7
-5 4
2 
Sample Input 2 Sample Output 2
3 2
1 2
1 3
3

读懂题意很重要(英语很重要)

第一种:把边和点都封装好,再来按正规的dfs操作

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

struct edge
{
    int head,tail;
    int color;
};
vector <edge> node[10005];//edge a[1000][1000];相当于这个
int vis[10005];
int cnt;
int bug;
int ans[10005];
void dfs(int n)
{
    int flag=0;
    for(int i=0;i<node[n].size();i++)//枚举顶点n的每一条边
    {

        if(node[n][i].color && bug)//black
        {
            if(vis[node[n][i].tail]) continue;//访问过了,不要放外面,放外面会把红边给pass掉
          bug=0;
          vis[node[n][i].tail]=1;
          dfs(node[n][i].tail);
          vis[node[n][i].tail]=0;
          bug=1;
        }
        else if(node[n][i].color==0)//red
        {
            flag=1;
            if(vis[node[n][i].tail]) continue;//访问过了,不要放外面,放外面会把红边给pass掉
            vis[node[n][i].tail]=1;
            dfs(node[n][i].tail);
            vis[node[n][i].tail]=0;
        }
    }
    if(flag==0)//这个点没有红边,可以stop
        {cnt++;ans[n]=1;}

}
int main()
{
    int n,m,x;
    edge t;
    cnt=0;
    bug=1;
    memset(vis,0,sizeof(vis));
    memset(ans,0,sizeof(ans));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&x,&t.tail);
        if(x>0)
            t.color=1;//black
        else
            t.color=0;//red
        t.head=abs(x);
        node[t.head].push_back(t);//把输入的边加入到节点中
    }
    vis[1]=1;
    dfs(1);
    //printf("%d\n",cnt);
    //cnt里面会有重复的点
    int tt=0;
    for(int i=1;i<=n;i++)
        if(ans[i]) tt++;
        printf("%d\n",tt);
    return 0;
}

第二种:充分理解题意,利用题目的各种条件剪枝,代码简洁一些

#include<bits/stdc++.h>
using namespace std;

int all[1005][1005];
int visit[1005];
int cannot[1005];

int n;
void dfs(int i,int flag,int time)
{
    int j;
    if(flag==2) return;
    if(time>visit[i]) return;
    if(time>900) return;
    visit[i]=time;
    for(j=1; j<=n; j++)
    {
        if(all[i][j]==2)
            dfs(j,flag,time+1);
        if(all[i][j]==1)
            dfs(j,flag+1,time+1);
    }
}
int main ()
{
    int m;
    int i,j,ans;
    scanf("%d %d",&n,&m);
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=n; j++)
        {
            all[i][j]=0;
        }
        visit[i]=99999;
        cannot[i]=0;
    }
    int a,b;
    while(m--)
    {
        scanf("%d%d",&a,&b);
        if(a>0)
        {
            all[a][b]=1;//black
        }
        if(a<0)
        {
            all[-a][b]=2;//red
            cannot[-a]=1;//首先把red边删除
        }
    }
    dfs(1,0,0);
    ans=0;
    for(i=1; i<=n; i++)
        if(visit[i]<=900&&cannot[i]==0)
            ans++;
    printf("%d\n",ans);
    return 0;
}

然而这两份代码我都不是我写的。。。。先记着吧。。。感觉写的不错。。。OvO.....

猜你喜欢

转载自blog.csdn.net/qq_40733911/article/details/81199905