zoukankan      html  css  js  c++  java
  • ZOJ 3811 Untrusted Patrol

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3811

    解题报告:一个无向图上有n个点和m条边,其中有k个点上安装了传感器,当有人第一次从安装了传感器的点上经过时,在控制室就会收到一个信号,现在保安制定 了一条路线目的是要将所有的点都巡逻一遍,然后在控制室收到了 L 次信号,按顺序给出收到信号的点,问这条路线是否是有可能的?

    路线的不可能的情况比如收到信号的点的顺序是123,但是在无向图上要到达2这个点必定先经过3,那么这种情况就是不可能的,因为要经过2之前必定经过3,所以2之前一定会有个3.这题的思路是这样的,用dfs从第一个点开始搜,当当前点的下一个点是没有传感器的可以直接走,如果有传感器的而且刚好是路线上的下一个点,也是直接走,如果是有传感器但又不是路线上的下一个点,则先把这个点放入到一个集合里面去,当所有能走的点都走完了,再在这个集合里面找路线上的下一个点是不是在这个集合里面,最后当集合空了的时候就可以退出了,而且每次走完点之后都要标记掉。另外两个重要的就是首先要判断L 是不是等于k,因为要走完所有的点,当L小于K时,走K-L 的这些点的时候肯定会发出信号,但这些信号又不是路线上的,所以不符合。另一个是要判断这个无向图是不是个连通图,这个简单,如果不是连通图必定会有走不到的点。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn = 100005;
      8 vector<int> vet[maxn];
      9 int flag[maxn];
     10 int T,n,m,k,l,L[maxn],cizi[maxn],visit[maxn],is[maxn],num;
     11 void find(int p,int* is)
     12 {
     13     if(is[p] == 1) return ;
     14     num++;
     15     is[p] = 1;
     16     for(int i = 0;i < vet[p].size();++i)
     17     find(vet[p][i],is);
     18 }        
     19          
     20 int is_connect(int n)   //判断是否是连通图 
     21 {
     22     num = 0;
     23     memset(is,0,sizeof(is));
     24     find(1,is);
     25     return num == n;
     26 }
     27 void dfs(int s,int* visit,int& p)
     28 {
     29     if(visit[s]) return ;
     30     visit[s] = 1;
     31     if(flag[s]) p++;
     32     for(int i = 0;i < vet[s].size();++i)
     33     {
     34         int nx = vet[s][i];
     35         if(flag[nx] && L[p+1] != nx)   //下一个点是有传感器的,但不是当前位置上的下一个点,则加入集合 
     36         cizi[nx] = 1;
     37         else dfs(nx,visit,p);
     38     }
     39 }
     40 
     41 int main()
     42 {
     43     
     44     scanf("%d",&T);
     45     while(T--)
     46     {
     47         scanf("%d%d%d",&n,&m,&k);
     48         int a,b;
     49         memset(flag,0,sizeof(flag));  //flag[i] = 1表示i点有传感器 
     50         for(int i = 1;i <= k;++i)
     51         {
     52             scanf("%d",&a);
     53             flag[a] = 1;
     54         }
     55         for(int i = 1;i <= n;++i)
     56         vet[i].clear();
     57         for(int i = 1; i<= m;++i)
     58         {
     59             scanf("%d%d",&a,&b);
     60             vet[a].push_back(b);
     61             vet[b].push_back(a);
     62         }
     63         scanf("%d",&l);
     64         for(int i = 1;i <= l;++i)
     65         scanf("%d",&L[i]);
     66         if(l != k || (!is_connect(n)))  //l < k或者不是连通图 
     67         {
     68         //    if(!is_connect(n)) puts("不是连通图"); 
     69             puts("No");
     70             continue;
     71         }
     72         int num_cizi = 1;
     73         memset(cizi,0,sizeof(cizi));  //把集合清空
     74         memset(visit,0,sizeof(visit));
     75         cizi[L[1]] = 1;   //路径上的第一个点加入集合
     76         int s = L[1],p = 0;   //当前走到的路径上的指针 
     77         while(p < l && cizi[s])
     78         {
     79             dfs(s,visit,p);
     80     //        printf("p = %d
    ",p);
     81             if(cizi[L[p+1]] == 1)
     82             s = L[p+1];
     83             else break;
     84         }
     85         printf(p == l? "Yes
    ":"No
    ");
     86     }
     87     return 0;
     88 }
     89 /*
     90 44
     91 6 6 6
     92 1 2 3 4 5 6
     93 1 6
     94 6 3
     95 6 2
     96 2 3
     97 2 5
     98 3 4
     99 6
    100 1 6 2 5 3 4
    101 */
    View Code
  • 相关阅读:
    站内信设计
    python 发送邮件例子
    mysql 索引相关知识
    一、mysql分表简单介绍
    redis 学习笔记三(队列功能)
    redis 学习笔记二 (简单动态字符串)
    redis 学习笔记一
    docker部署asp.net core
    win10安装docker
    页面格式化后台的传过来的
  • 原文地址:https://www.cnblogs.com/xiaxiaosheng/p/3969013.html
Copyright © 2011-2022 走看看