NOIp 2014 finding your way

Description

There is a right side \ (1 \) directed graph, there may be multiple edges from the ring.

Seeking a shortest path from the start point to the end point, the point that satisfies all the points on the path are edge points to communicate directly or indirectly with the end point.

When the game made this problem, the feeling is good road title.

Solution

Read out the sentence when safe special ring, seemingly irrelevant sentence can be.

First, build the reverse side, began to walk from the end, can be obtained which point to the end point.

Violence then calculated for each point can not join the path that it's all pointing to the side of the point can reach the end.

Then according to the edge weights \ (1 \) , running in the shortest bfs legitimate point.

Deep search can be used to achieve reverse sides built + bfs pretreatment, found to be a write ring stuck.

Therefore, similar to the pre-memory dfs search, consider change bfs.

Code

#include <bits/stdc++.h>
using namespace std;
#define re register
#define F first
#define S second
typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int N = 1e4 + 5, M = 2e5 + 5;
int read() {
    int x = 0, f = 0; char ch = 0;
    while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
    return f ? -x : x;
}
struct edge{
    int to, nxt;
}e[M];
int head[M], tot, dis[N];
void addedge(int x, int y){
    e[++tot].to = y; e[tot].nxt = head[x]; head[x] = tot;
}
int start[N], to[N];
bool can[N], allcan[N], vis[N];
int main(){
    int n = read(), m = read();
    for (int i = 1; i <= m; i++){
        int x = read(), y = read();
        start[i] = x; to[i] = y;
        if (x != y) addedge(y, x);
    }
    int s = read(), t = read();
    queue <int> q; q.push(t); 
    while (!q.empty()){
        int x = q.front(); q.pop(); can[x] = 1;
        for (int i = head[x]; i; i = e[i].nxt){
            int y = e[i].to;
            if (!vis[y]){
                vis[y] = can[y] = 1;
                q.push(y);
            }
        }
    }
    memset(head, 0, sizeof(head)); memset(vis, 0, sizeof(vis)); tot = 0;
    for (int i = 1; i <= m; i++)
        if (start[i] != to[i]) addedge(start[i], to[i]);
    for (int x = 1; x <= n; x++) {
        allcan[x] = can[x];
        for (int i = head[x]; i; i = e[i].nxt) 
            allcan[x] &= can[e[i].to];
    }
        
    if (allcan[s]) q.push(s), vis[s] = 1;
    while (!q.empty()){
        int x = q.front(); q.pop();
        if (x == t){
            printf("%d\n", dis[t]);
            return 0;
        }
        for (int i = head[x]; i; i = e[i].nxt){
            int y = e[i].to;
            if (allcan[y] && !vis[y]){
                vis[y] = 1; q.push(y);
                dis[y] = dis[x] + 1;
            }
        }
    }
    puts("-1");
    return 0;
}

Guess you like

Origin www.cnblogs.com/lyfoi/p/11443375.html