21.11.16模拟 学校

题意就是求出去掉一条边,还能按照原来的最短路的耗时从s到t

先一遍Dij求出s~t的最短路,然后从t bfs倒推回去,建立出最短路图C,然后在C上求割边
去掉的边若是C上的割边,那么就不能到达,否则能到达

const int N = 4e4 + 79;
const int M = 2e5 + 79;
struct graph {
	int head[N], tot = 1, next[M << 1], ver[M << 1], edge[M << 1], num[M << 1];
	inline void add(int id, int a, int b, int c) {
		ver[++tot] = b;
		num[tot] = id;
		next[tot] = head[a];
		head[a] = tot;
		edge[tot] = c;
	}
} G, C;
int n, m, s, t;
int d[N];
bool vis[N];
#define pii std::pair<int,int>
std::priority_queue<pii, std::vector<pii>, std::greater<pii> >Q;
inline void Dijkstra() {
	memset(d, 0x3f, sizeof d);
	d[s] = 0;
	Q.push({0, s});
	while(Q.size()) {
		int x(Q.top().second);
		Q.pop();
		if(vis[x]) continue;
		vis[x] = 1;
		repg(x) {
			int y(G.ver[i]), z(G.edge[i]);
			if(d[y] > d[x] + z) {
				d[y] = d[x] + z;
				Q.push({d[y], y});
			}
		}
	}
}
int low[N], dfn[N], tim;
bool bridge[M << 1];
inline void tarjan(int x, int in_edge) {
	low[x] = dfn[x] = ++tim;
	repc(x) {
		int y(C.ver[i]);
		if(!dfn[y]) {
			tarjan(y, i);
			low[x] = min(low[x], low[y]);

			if(low[y] > dfn[x]) {
				bridge[C.num[i]] = 1;
			}
		} else if(C.num[i] != C.num[in_edge]) {
			low[x] = min(low[x], dfn[y]);
		}
	}
}


int q[N];
inline void init() {
	memset(vis, 0, sizeof vis);
	vis[t] = 1;
	q[++q[0]] = t;
	rep(_, 1, q[0]) {
		int x(q[_]);
		repg(x) {
			int y(G.ver[i]), z(G.edge[i]);
			if(d[y]+z == d[x] ) {

				C.add(G.num[i], x, y, z);
				C.add(G.num[i], y, x, z);
				if(!vis[y]) {
					vis[y] = 1;
					q[++q[0]] = y;
				}
			}
		}
	}
	tarjan(s, -1);
}

int main() {
	freopen("school.in","r",stdin);
	freopen("school.out","w",stdout);
	read(n);
	read(m);
	read(s);
	read(t);
	int a, b, c;
	rep(i, 1, m) {
		read(a);
		read(b);
		read(c);
		G.add(i, a, b, c);
		G.add(i, b, a, c);
	}
	Dijkstra();
	init();
	int Q, x;
	read(Q);
	while(Q--) {
		read(x);
		puts(bridge[x] ? "No" : "Yes");
	}
	return 0;
}

本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15566296.html

原文地址:https://www.cnblogs.com/QQ2519/p/15566296.html