noip2014 尋找道路


P2296 尋找道路

    • 707通過
    • 2.6K提交
  • 題目提供者該用戶不存在
  • 標簽圖論2014NOIp提高組
  • 難度普及+/提高

提交該題 討論 題解 記錄

最新討論

題目描述

在有向圖G 中,每條邊的長度均為1 ,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件:

1 .路徑上的所有點的出邊所指向的點都直接或間接與終點連通。

2 .在滿足條件1 的情況下使路徑最短。

注意:圖G 中可能存在重邊和自環,題目保證終點沒有出邊。

請你輸出符合條件的路徑的長度。

輸入輸出格式

輸入格式:

 

輸入文件名為road .in。

第一行有兩個用一個空格隔開的整數n 和m ,表示圖有n 個點和m 條邊。

接下來的m 行每行2 個整數x 、y ,之間用一個空格隔開,表示有一條邊從點x 指向點y 。

最后一行有兩個用一個空格隔開的整數s 、t ,表示起點為s ,終點為t 。

 

輸出格式:

 

輸出文件名為road .out 。

輸出只有一行,包含一個整數,表示滿足題目᧿述的最短路徑的長度。如果這樣的路徑不存在,輸出- 1 。

 

輸入輸出樣例

輸入樣例#1:
3 2  
1 2  
2 1  
1 3  
輸出樣例#1:
-1
輸入樣例#2:
6 6  
1 2  
1 3  
2 6  
2 5  
4 5  
3 4  
1 5  
輸出樣例#2:
3

說明

解釋1:

如上圖所示,箭頭表示有向道路,圓點表示城市。起點1 與終點3 不連通,所以滿足題

目᧿述的路徑不存在,故輸出- 1 。

解釋2:

如上圖所示,滿足條件的路徑為1 - >3- >4- >5。注意點2 不能在答案路徑中,因為點2連了一條邊到點6 ,而點6 不與終點5 連通。

對於30%的數據,0<n≤10,0<m≤20;

對於60%的數據,0<n≤100,0<m≤2000;

對於100%的數據,0<n≤10,000,0<m≤200,000,0<x,y,s,t≤n,x≠t。

吐槽:把出邊看漏了,然后就一直WA,把tot忘了清0,i=next[i]寫成了i++,一直RE......

分析:首先,怎么知道一個點i是否與終點連通呢?可以floyd,但是對於這道題就不需要了,從終點反向一次bfs,能標記到的點就是能訪問到的,因為邊權為1,求最短路從起點再來一次bfs即可.每次擴展之前都要先判斷出邊有沒有被標記,從終點bfs了一次過后一定要將用過的數組清0.

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 10010, maxm = 200010;

int n, m,first,tail,x[maxm],y[maxm],nextt[maxm * 2],to[maxm * 2],head[maxm],tot,s,t,q[maxn],step[maxn];
bool vis[maxn];

void add(int a, int b)
{
    to[++tot] = b;
    nextt[tot] = head[a];
    head[a] = tot;
}

void bfs1()
{
    q[0] = t;
    vis[t] = true;
    first = 0;
    tail = 1;
    while (first < tail)
    {
        int u = q[first++];
        for (int i = head[u];i;i = nextt[i])
        {
            if (!vis[to[i]])
            {
                vis[to[i]] = true;
                q[tail++] = to[i];
            }
        }
    }
}

bool chubian(int q)
{
    for (int i = head[q]; i; i = nextt[i])
        if (!vis[to[i]])
            return false;
    return true;
}

bool bfs2()
{
    first = 0;
    tail = 1;
    q[0] = s;
    step[s] = 0;
    while (first < tail)
    {
        int u = q[first++];
        if (!chubian(u))
            continue;
        for (int i = head[u]; i; i = nextt[i])
        {
            if (step[to[i]] == -1)
            {
                step[to[i]] = step[u] + 1;
                q[tail++] = to[i];
                if (to[i] == t)
                {
                    printf("%d", step[to[i]]);
                    return true;
                }
            }
        }
    }
    return false;
}

int main()
{
    memset(vis, false, sizeof(vis));
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d", &x[i], &y[i]);
        add(y[i], x[i]); //反着加便於反着bfs
    }
    scanf("%d%d", &s,&t);
    bfs1();
    memset(head, 0, sizeof(head));
    memset(step, -1, sizeof(step));
    memset(q, 0, sizeof(q));
    memset(nextt, 0, sizeof(nextt));
    memset(to, 0, sizeof(to));
    tot = 0;
    for (int i = 1; i <= m; i++)
        add(x[i], y[i]);
    if (!vis[s])
    {
        printf("-1\n");
        return 0;
    }
    if (!bfs2())
        printf("-1\n");

    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM