• luogu P2296 寻找道路


    题目链接:luogu P2296 寻找道路

    题目大意:

    题解:
    首先想到的就是求单源最短路,所以选择用优先队列优化的Dijkstra算法。
    由于存在限制:路径上的点及其子节点都必须可以到达终点。
    所以首先反向建边并从终点开始BFS标记所有能够到达终点的点,再在所有标记的点中剔除存在不能到达终点的子节点的点。
    最后就是在满足条件的点中跑Dijkstra。

    #include <iostream>
    #include <queue>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define N 10000 + 10
    #define M 200000 + 10
    
    int n, m, head[N], cnt, _head[N], dis[N], s, t;
    bool reach[N], mark[N];
    struct Edge {
    	int v, len, next;
    } e[M], _e[M];
    struct Node {
    	int u, dis;
    	bool operator < (const Node &x) const {
    		return dis > x.dis;
    	}
    };
    
    void AddEdge(int u, int v, int w) {
    	e[++cnt].v = v;
    	e[cnt].len = w;
    	e[cnt].next = head[u];
    	head[u] = cnt;
    	_e[cnt].v = u;
    	_e[cnt].len = w;
    	_e[cnt].next = _head[v];
    	_head[v] = cnt;
    }
    
    void bfs(int t) {
    	queue <int> q;
    	reach[t] = true;
    	q.push(t);
    	while (!q.empty()) {
    		int u = q.front();
    		q.pop();
    		for (int i = _head[u]; i; i = _e[i].next) {
    			if (!reach[_e[i].v]) {
    				reach[_e[i].v] = true;
    				q.push(_e[i].v);
    			}
    		}
    	}
    }
    
    void Mark() {
    	for (int i = 1; i <= n; ++i) {
    		if (reach[i]) {
    			mark[i] = true;
    			for (int j = head[i]; j; j = e[j].next) {
    				if (!reach[e[j].v]) {
    					mark[i] = false;
    					break;
    				}
    			}
    		}
    	}
    }
    
    void dijkstra(int s) {
    	priority_queue <Node> q;
    	for (int i = 1; i <= n; ++i) {
    		dis[i] = INF;
    	}
    	dis[s] = 0;
    	q.push(Node{s, 0});
    	while (!q.empty()) {
    		int u = q.top().u, d = q.top().dis;
    		q.pop();
    		if (d > dis[u])	continue;
    		for (int i = head[u]; i; i = e[i].next) {
    			int v = e[i].v, len = e[i].len;
    			if (!mark[v])	continue;
    			if (dis[v] > dis[u] + len) {
    				dis[v] = dis[u] + len;
    				q.push(Node{v, dis[v]});
    			}
    		}
    	}
    }
    
    int main() {
    	io_speed_up;
    	cin >> n >> m;
    	for (int i = 1; i <= m; ++i) {
    		int u, v;
    		cin >> u >> v;
    		AddEdge(u, v, 1);
    	}
    	cin >> s >> t;
    	bfs(t);
    	Mark();
    	dijkstra(s);
    	if (dis[t] != INF) {
    		cout << dis[t] << endl;
    	} else {
    		cout << -1 << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU 2842 (递推+矩阵快速幂)
    HDU 2838 (DP+树状数组维护带权排序)
    HDU 2836 (离散化DP+区间优化)
    HDU 2831 (贪心)
    HDU 2818 (矢量并查集)
    HDU 2822 (BFS+优先队列)
    HDU 3090 (贪心)
    HDU 3089 (快速约瑟夫环)
    XCOJ 1103 (LCA+树链最大子段和)
    HDU 3078 (LCA+树链第K大)
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/13986805.html
Copyright © 2020-2023  润新知