ACM: 广搜 图论题 poj 1708

                                                                                        Game

 

Description

A child has drawn N (N<=100) numbered circles of different colors. He has connected some of the circles by colored oriented line segments. Every pair of circles may have any number of segments, with any colors, connecting them. Each color (either circle color or segment color) is assigned its own unique positive integer number not greater than 100.

Starting the game the child first of all chooses three different integers L, K and Q within the range between 1 and N. Then he places one pawn into the circle number L and another one into the circle number K, whereupon he begins to move them using the following rules:
  • a pawn can be moved along the line segment, if this segment has the same color with the circle where another pawn is placed,
  • the pawn can be moved only in the direction of the segment (all segments are oriented),
  • two pawns can never be placed in the same circle at the same time,
  • the move order is free (i.e. it is not necessary to move pawns alternately),
  • the game ends, when one of the pawns (any of the two) reaches the last circle number Q.

You are to write a program to find out the shortest (i.e. containing a minimal number of moves) solution for this game, if it exists.

Input

The first line of the input file contains integers N, L, K, Q separated by spaces. The second line consists of N integers c1, c2, ... , cn, separated by spaces, in the given order, where ci is the color of the circle number i. The third line consists of a single integer M (0<=M<=10000) denoting the total number of segments. Then follow M lines, each containing a description of one oriented segment. Each segment is described by three integer numbers Aj, Bj, Cj, separated by spaces, where A and B are the numbers of the circles connected by the j-th segment with direction from Aj to Bj, and Cj represents the color of this segment.

Output

The first line of the output file should contain the word "YES", if the game can come to the end, and "NO" otherwise (without quotes). If the answer is "YES", the second line of the output should contain just a single integer - the minimum number of the moves the child should make to finish the game.

Sample Input

5 3 4 1
2 3 2 1 4
8
2 1 2
4 1 5
4 5 2
5 1 3
3 2 2
3 2 4
5 3 1
3 5 1

Sample Output

YES
3

题意: 现在有两个点, L,K为两个起点编号, 计算最少的移动次数到达Q点, 若可以就输出YES和最少步数,

      否则输出NO.

      但是没移动一次有要求:

                         1. 只可以沿着线段方向移动.

                         2. 两个人不可以同时移动到同一个点上.

                         3. 移动次序是随意的.

                         4. 谁先到达就结束游戏.

解题思路:

          1. 广搜第一反应. 也是正确的.

          2. 怎么广搜呢? 用什么数据类型? 现在开始会思考这些问题. (进步了!!)

          3. 设每个队列的节点同时存在L,K的当前位置, 即使假设他们同步进行行走, 模拟过程.

          4. 主要是要记得判断他们不可以同时移动到同一个点上.

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define MAX 105
const int INF = (1<<29);

struct node
{
 int v;
 int color;
 int next;
}edges[MAX*MAX];

struct node1
{
 int posL, posK;
 int step;
};

int N, L, K, Q, m;
int first[MAX], num;
bool vis[MAX][MAX];
int color[MAX];
int result;

inline void add(int u,int v,int co)
{
 edges[num].v = v;
 edges[num].color = co;
 edges[num].next = first[u];
 first[u] = num++;
}

void read_graph()
{
 memset(vis,false,sizeof(vis));
 memset(first,-1,sizeof(first));
 memset(edges,0,sizeof(edges));
 num = 0;
 scanf("%d",&m);
 int u, v, co;
 int i;
 for(i = 1; i <= m; ++i)
 {
  scanf("%d %d %d",&u,&v,&co);
  add(u,v,co);
 }
}

bool bfs()
{
 queue<node1> qu;
 node1 temp;
 temp.posK = K, temp.posL = L, temp.step = 0;
 vis[K][L] = true;
 qu.push(temp);
 bool flag = false;
 int e;
 result = INF;
 
 while( !qu.empty() )
 {
  temp = qu.front();
  qu.pop();
  if(temp.posK == Q || temp.posL == Q)
  {
   if(temp.step < result) result = temp.step;
   flag = true;
  }

  for(e = first[temp.posL]; e != -1; e = edges[e].next)
  {
   if(!vis[ edges[e].v ][ temp.posK ] && edges[e].v != temp.posK && edges[e].color == color[temp.posK])
   {
    vis[ edges[e].v ][ temp.posK ] = true;
    node1 t;
    t.posK = temp.posK;
    t.posL = edges[e].v;
    t.step = temp.step+1;
    qu.push(t);
   }
  }

  for(e = first[temp.posK]; e != -1; e = edges[e].next)
  {
   if( !vis[ temp.posL ][ edges[e].v ] && edges[e].v != temp.posL && edges[e].color == color[temp.posL] )
   {
    vis[ temp.posL ][ edges[e].v ] = true;
    node1 t;
    t.posK = edges[e].v;
    t.posL = temp.posL;
    t.step = temp.step+1;
    qu.push(t);
   }
  }
 }

 return flag;
}

int main()
{
 int i;
// freopen("input.txt","r",stdin);
 while(scanf("%d %d %d %d",&N,&L,&K,&Q) != EOF)
 {
  for(i = 1; i <= N; ++i)
   scanf("%d",&color[i]);
  read_graph();
  if( !bfs() )
   printf("NO\n");
  else
   printf("YES\n%d\n",result);
 }

 return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值