zoukankan      html  css  js  c++  java
  • [UOJ] #19 寻找道路

    #19. 寻找道路NOIP2014

    在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

    1. 路径上的所有点的出边所指向的点都直接或间接与终点连通。
    2. 在满足条件 1 的情况下使路径最短。

    注意:图 GG 中可能存在重边和自环,题目保证终点没有出边。

    请你输出符合条件的路径的长度。

    输入格式

    第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边。

    接下来的 mm 行每行 22 个整数 x,yx,y,之间用一个空格隔开,表示有一条边从点 xx 指向点yy。

    最后一行有两个用一个空格隔开的整数 s,ts,t,表示起点为 ss,终点为 tt。

    输出格式

    输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出1−1。

    样例一

    input

    3 2
    1 2
    2 1
    1 3
    
    

    output

    -1
    
    

    explanation

    起点11与终点33不连通,所以满足题目描述的路径不存在,故输出1−1。

    样例二

    input

    6 6
    1 2
    1 3
    2 6
    2 5
    4 5
    3 4
    1 5
    
    

    output

    3
    
    

    explanation

    注意点22不能在答案路径中,因为点22连了一条边到点66,而点66不与终点55连通。

    限制与约定

    对于30%的数据,0<n100<n≤10,0<m200<m≤20;

    对于60%的数据,0<n1000<n≤100,0<m20000<m≤2000;

    对于100%的数据,0<n100000<n≤10000,0<m2000000<m≤200000,0<x,y,s,tn0<x,y,s,t≤n,x,stx,s≠t。

    时间限制:1s1s

    内存限制:128MB

    分析

    本来思路是 “反向存图+终点SPFA+额外判断” 求合法点集,然后 “起点SPFA” 求最短路。

    结果一波挂残,20分 = =

    后来决定用终点做根朴素DFS判断合法点集,再次20分 = =

    关键在合法点集,根据样例合法点集内的点每一条出边都需要能到达终点,那么像样例2中的结点2是不能包括进合法点集的,此处需要注意实现部分。

    代码

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #define maxn 500000
      5 using namespace std;
      6 
      7 struct edge{
      8     int from,v;
      9 }e[maxn],e1[maxn];
     10 
     11 const int inf = 999999999;
     12 
     13 int n,m,a,b,que[maxn*100],head,tail,s,t,dis[maxn];
     14 bool book[maxn],chose[maxn];
     15 int tot,tot1,first[maxn],first1[maxn];
     16 void insert(int u,int v){
     17     tot++;
     18     e[tot].from = first[u];
     19     e[tot].v = v;
     20     first[u] = tot;
     21 }
     22 
     23 void insert1(int u,int v){
     24     tot1++;
     25     e1[tot1].from = first1[u];
     26     e1[tot1].v = v;
     27     first1[u] = tot1;
     28 }
     29 
     30 void dfs(int now){
     31     for(int i = first1[now];i;i = e1[i].from){
     32         int v = e1[i].v;
     33         if(!book[v]){
     34             book[v] = true;
     35             dfs(v);
     36         }
     37     }
     38 }
     39 
     40 void PRINT(){
     41     printf("#dis:  ");
     42     for(int i = 1;i <= n;i++) printf("%d ",dis[i]);
     43     cout << endl;
     44 }
     45 
     46 void SPFA(){
     47     for(int i = 1;i <= n;i++)
     48         book[i] = false,dis[i] = inf;
     49     head = tail = 0;
     50     que[head++] = s;
     51     book[s] = true;
     52     dis[s] = 0;
     53     
     54 //    PRINT();
     55     
     56     while(head > tail){
     57         int p = que[tail++];
     58         for(int i = first[p];i;i = e[i].from){
     59             int v = e[i].v;
     60             if(dis[v] > dis[p]+1){
     61                 dis[v] = dis[p]+1;
     62                 if(book[v]) continue;
     63                 book[v] = true;
     64                 que[head++] = v;
     65             }
     66         }book[p] = false;
     67     }
     68     
     69 //    PRINT();
     70     
     71     if(dis[t] < inf) printf("%d",dis[t]);
     72     else printf("-1");
     73 }
     74 
     75 int main(){
     76     scanf("%d%d",&n,&m);
     77     
     78     for(int i = 1;i <= m;i++){
     79         scanf("%d%d",&a,&b);
     80         insert1(b,a);
     81     }
     82     
     83     scanf("%d%d",&s,&t);
     84     
     85     book[t] = true;
     86     dfs(t);
     87     
     88     memset(chose,true,sizeof(chose));
     89         
     90     for(int i = 1;i <= n;i++){
     91         if(book[i]) continue;
     92         for(int j = first1[i];j;j = e1[j].from){
     93             int v = e1[j].v;
     94             if(!book[v] || !book[i]){
     95                 chose[v] = false;
     96             }
     97         }
     98     }
     99     
    100 //    cout << "----------------------------" << endl;
    101     for(int i = 1;i <= n;i++){
    102         if(!chose[i]) continue;
    103         for(int j = first1[i];j;j = e1[j].from){
    104             int v = e1[j].v;
    105             if(chose[v]){
    106 //                printf("%d %d
    ",v,i);
    107                 insert(v,i);
    108             }
    109         }
    110     }
    111     
    112 //    for(int i = 1;i <= n;i++){
    113 //        printf("%c",chose[i]?'T':'F');
    114 //        printf("%c ",book[i]?'T':'F');
    115 //    }
    116     
    117     SPFA();
    118     
    119     return 0;
    120 }
    死于细节
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    JS中声明变量的细节问题
    你不知道的var! 细节
    读书笔记:对象的属性
    手写new操作符
    slice
    全相等函数 isEqual
    几个面试题
    全相等函数
    剑指 Offer 29. 顺时针打印矩阵
    剑指 Offer 28. 对称的二叉树
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7373533.html
Copyright © 2011-2022 走看看