USACO Section 4.3 Street Race - 简单搜索


    50个点...100条边....数据量很小...第一问就直接枚举去掉每个点看能否到达终点~~~N次BFS就ok了...

    第二问~~首先第二问的点肯定是第一问的点的子集~~这个应该好想到..然后就按他的描述...枚举第一问得到的点..从起点开始BFS到枚举的这个点记录能到达的点..从枚举的这个点开始BFS到终点并记录所能到达的点...若两者标记的点中没有重复则说明这个第一问的点同时满足第二问的要求~


Program:

/*  
ID: zzyzzy12   
LANG: C++   
TASK: race3
*/      
#include<iostream>      
#include<istream>  
#include<stdio.h>     
#include<string.h>      
#include<math.h>      
#include<stack>
#include<map>
#include<algorithm>      
#include<queue>   
#define oo 1000000000  
#define ll long long  
#define pi (atan(2)+atan(0.5))*2 
using namespace std;  
struct node
{
      int x,y,next;    
}line[305];
int n,m,_link[55],Ans1[55],Ans1Num;
bool used[55];
queue<int> myqueue;
void getanswer1()
{
      int p=1,h,k; 
      Ans1Num=0;
      for (p=1;p<n;p++)
      {
            while (!myqueue.empty()) myqueue.pop();
            memset(used,false,sizeof(used));
            used[p]=true; used[0]=true;
            myqueue.push(0);
            while (!myqueue.empty())
            { 
                   h=myqueue.front();
                   myqueue.pop();
                   k=_link[h];
                   while (k)
                   {
                         if (!used[line[k].y])
                         {
                               used[line[k].y]=true;
                               myqueue.push(line[k].y);                     
                         }
                         k=line[k].next;      
                   }
            }
            if (!used[n])
                Ans1[++Ans1Num]=p;                        
      }
      printf("%d",Ans1Num);
      for (p=1;p<=Ans1Num;p++) printf(" %d",Ans1[p]);
      printf("\n");
      return;
}
void getanswer2()
{
      int Ans2Num,Ans2[55],p,h,k;
      bool f[55];
      Ans2Num=0;
      for (p=1;p<=Ans1Num;p++)
      {
             while (!myqueue.empty()) myqueue.pop();
             memset(f,false,sizeof(f));
             f[Ans1[p]]=true; myqueue.push(Ans1[p]);
             while (!myqueue.empty())
             {
                     h=myqueue.front();
                     myqueue.pop(); 
                     k=_link[h];
                     while (k)
                     {
                           if (!f[line[k].y])
                           {
                                f[line[k].y]=true;
                                myqueue.push(line[k].y);                     
                           }
                           k=line[k].next;
                     }
             } 
             memset(used,false,sizeof(used));
             used[0]=true; myqueue.push(0);
             while (!myqueue.empty())
             {
                    h=myqueue.front();
                    myqueue.pop();
                    if (h==Ans1[p]) continue;
                    if (f[h]) goto A; 
                    k=_link[h];
                    while (k)
                    {
                           if (!used[line[k].y])
                           {
                                 used[line[k].y]=true;
                                 myqueue.push(line[k].y);                     
                           }
                           k=line[k].next;
                    }                    
             }
             Ans2[++Ans2Num]=Ans1[p];
             A: ;
      }
      printf("%d",Ans2Num);
      for (k=1;k<=Ans2Num;k++) printf(" %d",Ans2[k]);
      printf("\n");
      return;
}
int main()  
{  
      freopen("race3.in","r",stdin);   
      freopen("race3.out","w",stdout);   
      int i,y; 
      m=0; n=-1;
      memset(_link,0,sizeof(_link));
      while (1)
      { 
             scanf("%d",&y);
             if (y==-1) break;
             n++;
             while (y!=-2)
             {
                   m++;
                   line[m].x=n; line[m].y=y;
                   line[m].next=_link[n]; _link[n]=m;
                   scanf("%d",&y);     
             }
      } 
      getanswer1();    
      getanswer2();  
      return 0;     
}   


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值