飞翔的小鸟

时间:2019-11-15
本文章向大家介绍飞翔的小鸟,主要包括飞翔的小鸟使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<stack>
#include<map>
#define maxn 200110
using namespace std;

int top;
typedef long long ll;
int n, m, q;
stack<int>s;
struct Node {
	int p;
	int len;
	Node(int a, int b) :p(a), len(b) {}
};
int maxx[maxn*3];//1到i的最大值
int minn[maxn*3];//1到i的最小值
vector<Node>G[maxn], G2[3*maxn];
void insert(int be, int en, int len) {
	G[be].push_back(Node(en, len));
}
int dfn[maxn], low[maxn], df, clor[maxn], ans;
int list[maxn];
int cn = 0;
int tarjan(int x) {
	low[x] = dfn[x] = ++df;
	s.push(x);
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i].p;
		if (!dfn[p]) {
			tarjan(p);
			low[x] = min(low[x], low[p]);
		}
		else if (!clor[p]) {
			low[x] = min(low[x], dfn[p]);
		}
	}
	if (dfn[x] == low[x]) {
		ans++;
		while (1) {
			int a = s.top();
			s.pop();
			clor[a] = ans;
			if (a == x) break;
		}
	}
	return 0;
}
int de[maxn*3];

int num = 0;
int LL[maxn], mid[maxn], RR[maxn];
int find_() {
	
	tarjan(1);
	for (int i = 1; i <= n; i++) list[clor[i]]++;
	for (int i = 1; i <= ans; i++) {
		if (list[i] > 1) {
			LL[i] = ++num; mid[i] = ++num; RR[i] = ++num;
		}
		else {
			LL[i] = mid[i] = RR[i] = ++num;
		}
	}

	for (int i = 1; i <= n; i++) minn[i] = 1e9 + 10000;

	for (int i = 1; i <= n; i++) {
		if (!dfn[i]) continue;

		for (int j = 0; j < G[i].size(); j++) {
			int be = clor[i];
			int en = clor[G[i][j].p];
			if (be == en) {
				maxx[be] = max(maxx[be], G[i][j].len);
				minn[be] = min(minn[be], G[i][j].len);
			}
			else {
				G2[RR[be]].push_back(Node(LL[en], G[i][j].len));
				de[LL[en]]++;
			}
		}
	}
	for (int i = 1; i <= ans; i++) {
		if (list[i] > 1) {
			G2[LL[i]].push_back(Node(mid[i], maxx[i]));
			G2[mid[i]].push_back(Node(RR[i], minn[i]));

			de[mid[i]]++;
			de[RR[i]]++;
		}
	}
	return 0;
}
int chal[maxn*3];
int topu() {
	queue<int>que;
	memset(chal, -1, sizeof(chal));
	memset(maxx, -1, sizeof(maxx));

	for (int i = 1; i <= num; i++) minn[i] = 0x3f3f3f3f;
	for (int i = 1; i <= num; i++) if (de[i] == 0) que.push(i);
	while (!que.empty()) {
		int x = que.front();
		que.pop();
		for (int i = 0; i < G2[x].size(); i++) {
			int p = G2[x][i].p;
			int ln = G2[x][i].len;
			de[p]--;
			int tx = max(maxx[x], ln), tm = min(minn[x], ln);
			maxx[p] = max(maxx[p], tx);
			minn[p] = min(minn[p], tm);
			chal[p] = max(chal[p], max(chal[x], max(tx - ln, ln - tm)));
			if (!de[p]) {
				que.push(p);
			}
		}
	}

	return 0;
}

int main() {
	int be, en, len;
	scanf("%d %d %d", &n, &m, &q);
	for (int i = 0; i < m; i++) {
		scanf("%d %d %d", &be, &en, &len);
		insert(be, en, len);
	}
	
	find_();//缩点,建边
	topu();
	int xx;
	
	while (q--) {
		scanf("%d", &be);
		
		if (!dfn[be] ) printf("-1\n");
		else printf("%d\n", chal[RR[clor[be]]]);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/lesning/p/11865914.html