Comet OJ(Contest #14)-飞翔的小鸟【tarjan】

正题

题目链接:https://www.cometoj.com/contest/73/problem/E?problem_id=4124


题目大意

给出\(n\)个点\(m\)条边的一张有向图,边有边权,\(q\)次询问从点\(1\)走到点\(x\)的所有路径(可以重复经过任何点包括点\(x\))中极差最大是多少。

\(1\leq n\leq 2\times 10^5,1\leq m\leq 5\times 10^5\)


解题思路

首先肯定要\(tarjan\)缩点,然后考虑怎么统计极差。

考虑到极差其实到某个位置的时候就已经不会再改变了,而且这个到这个位置的路径一定是作为最小值或者最大值的。

所以我们可以维护一个路径上的最大值/最小值和最大极差,然后每次考虑新的转移会不会更新极差就可以了。

时间复杂度:\(O(n+m)\)

CometOJ评测机炸了,代码没测就当过了吧...


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=2e5+10;
int n,m,t,cnt,dfn[N],low[N],col[N],in[N];
int mi[N],mx[N],Mi[N],Mx[N],ans[N];
stack<int> s;queue<int> q;bool ins[N];
vector<pair<int,int> > G[N],T[N];
void tarjan(int x){
	dfn[x]=low[x]=++cnt;
	ins[x]=1;s.push(x);
	for(int i=0;i<G[x].size();i++){
		int y=G[x][i].first;
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(ins[y])
			low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		while(s.top()!=x){
			col[s.top()]=x;
			ins[s.top()]=0;
			s.pop();
		}
		col[x]=x;ins[x]=0;
		s.pop();
	}
	return;
}
void Topsort(){
 	for(int i=1;i<=n;i++)
		if(!in[i])q.push(i);
	while(!q.empty()){
		int x=q.front();q.pop();
		Mx[x]=max(Mx[x],mx[x]);
		Mi[x]=min(Mi[x],mi[x]);
		ans[x]=max(ans[x],mx[x]-Mi[x]);
		ans[x]=max(ans[x],Mx[x]-mi[x]);
		for(int i=0;i<T[x].size();i++){
			int y=T[x][i].first,w=T[x][i].second;
			in[y]--;
			Mx[y]=max(Mx[y],max(Mx[x],w));
			Mi[y]=min(Mi[y],min(Mi[x],w));
			ans[y]=max(ans[y],ans[x]);
			ans[y]=max(ans[y],w-Mi[x]);
			ans[y]=max(ans[y],Mx[x]-w);
			if(!in[y])q.push(y);
		}
	}
	return;
}
int main()
{
	scanf("%d%d%d",&n,&m,&t);
	for(int i=1;i<=m;i++){
		int x,y,w;
		scanf("%d%d%d",&x,&y,&w);
		G[x].push_back(mp(y,w));
	}
	tarjan(1);
	memset(mi,0x3f,sizeof(mi));
	memset(Mi,0x3f,sizeof(Mi));
	for(int x=1;x<=n;x++){
		for(int i=0;i<G[x].size();i++){
			int y=G[x][i].first,w=G[x][i].second;y=col[y];
			if(col[x]==y)mx[y]=max(mx[y],w),mi[y]=min(mi[y],w);
			else T[col[x]].push_back(mp(y,w)),in[y]++;
		}
	}
	Topsort();
	while(t--){
		int x;
		scanf("%d",&x);
		if(x==1||!col[x])puts("-1");
		else printf("%d\n",ans[col[x]]);
	}
	return 0;
}
posted @ 2021-10-19 21:10  QuantAsk  阅读(37)  评论(3编辑  收藏  举报