• 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;
    }
    
  • 相关阅读:
    Java学习之Java历史版本
    小数的二进制转换
    cpp反汇编调试一
    理解 typedef 定义的函数指针
    mov 与 lea 区别
    asmlinkage的用法
    秒的换算:ms(毫秒),μs(微秒),ns(纳秒),ps(皮秒)
    Java字节码例子解析
    Go程序的一生是怎样的?
    Linux内核 hlist_head/hlist_node结构解析
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15426482.html
Copyright © 2020-2023  润新知