Faulty Robot

Faulty Robot

题目描述

As part of a CS course, Alice just finished programming her robot to explore a graph having n nodes, labeled 1, 2, . . . , n, and m directed edges. Initially the robot starts at node 1.
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 5 has outgoing edges to neighbors 1, 4, and 6 but that Alice programs the robot so that if it leaves 5 it must go to neighbor 4.
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 G.1 and G.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.
In the first example, the robot will cycle forever through nodes 1, 5, and 4 if it does not make a buggy move.
A bug could cause it to jump from 1 to 2, but that would be the only buggy move, and so it would never move on from there. It might also jump from 5 to 6 and then have a forced move to end at 7.
In the second example, there are no forced moves, so the robot would stay at 1 without any buggy moves. It might also make a buggy move from 1 to either 2 or 3, after which it would stop.

输入

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

输出

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

样例输入

7 9
1 2
2 3
-1 5
2 6
5 1
-4 1
5 6
-6 7
-5 4

样例输出

2
题目大意:有n个点,从1到n中有m条有向连接线段,从1作为初始点出发,默认情况下只能沿着红色的有
向线段走。可以在行走的任意一点发生BUG,即可以在任意一点沿着黑线一步,在行走的路径中,最多
出现一次bug。因为是有向连接线段,最终的状态只能是停止在某一点,或者在卡在一个循环体。问最终
可以停留的点的数目。
解题思路:因为在行走过程中的每个点都有可能发生bug,所以先bfs枚举出无bug 时的所能够到达的点,
这些点就是可以出现bug 的点。然后对这些点第一次走黑线,再dfs。最终查看叶子结点的种类。(循环体
不要加进去)
给出c++代码:
#include<stdio.h>
#include<string.h>
#include<vector>   //采用动态数组储存
#include<queue>
#include<algorithm>
using namespace std;
int vis[1010];                    // 对走过的所有点做标记 
int flag[1010];	                 //dfs时的标记数组
int endd[1010];                 //记录叶子结点的种类
vector<int> red[1010];          //储存红色有向线段
vector<int> black[1010];        //储存黑色有向线段
int bac[1010]={0};             //来记录没有bug时,沿红边所能够到达的点,即可以发生bug 的点 
int t,countt;
int n,m;
void dfs(int indx)
{
	int i;
	if(vis[indx]==1||flag[indx]==1)
		return ;
	
	if(red[indx].size()==0){
		//countt++;             //可能通过不同的路径到达同一个点,不能累加,只能记录种类数
		endd[indx]=1;
	}
	
	flag[indx]=1;
	for(i=0;i<red[indx].size();i++){
		dfs(red[indx][i]);
		flag[indx]=1;
	}
	
}
void bfs()
{
	int now,i;
	queue<int> q;
	memset(vis,0,sizeof(vis));
	
	q.push(1);
	t=0;
	bac[t++]=1;  
	vis[1]=1;     
	
	while(!q.empty()){
		now=q.front();
		q.pop();
		
		if(red[now].size()==0){
			countt++;
			vis[now]=1;
			continue;
		}
		for(i=0;i<red[now].size();i++){
			if(vis[red[now][i]]==0){
				vis[red[now][i]]=1;
				bac[t++]=red[now][i];
				q.push(red[now][i]);
			}
		}
	}
	
}
int main()
{	int i,j,u,v;
	memset(flag,0,sizeof(flag));
	memset(endd,0,sizeof(endd));
	
	scanf("%d %d",&n,&m);
	countt=0;
	t=0;
	
	for(i=0;i<m;i++){
		scanf("%d %d",&u,&v);
		if(u<0)
			red[-u].push_back(v);
		else
			black[u].push_back(v);
	}
	
	bfs();
	
	for(i=0;i<t;i++){
		if(black[bac[i]].size()==0)
			continue;
		for(j=0;j<black[bac[i]].size();j++){
			//if(vis[black[bac[i]][j]]==0)
				dfs(black[bac[i]][j]);
		}
	}
	
	for(i=1;i<=n;i++){
		if(endd[i]==1)
			countt++;
	}
	
	printf("%d\n",countt);
	
	return 0;
}
解题心得:额.........这次没什么心得,要走的路还很远。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值