zoukankan      html  css  js  c++  java
  • Codeforces960F. Pathwalks

    description

    You are given a directed graph with n nodes and m edges, with all edges having a certain weight.

    There might be multiple edges and self loops, and the graph can also be disconnected.

    You need to choose a path (possibly passing through same vertices multiple times) in the graph such that the weights of the edges are in strictly increasing order, and these edges come in the order of input. Among all such paths, you need to find the the path that has the maximum possible number of edges, and report this value.

    Please note that the edges picked don't have to be consecutive in the input.

    题目大意:给你一张n个点m条边的带权有向图,可能有重边和自环。边会按照顺序给出。让你求出一条最长的路径,使得路径上的边满足边权和出现的时间严格递增。路径可以重复经过同一个点。

    Examples

    input

    3 3
    3 1 3
    1 2 1
    2 3 2
    

    output

    2
    

    input

    5 5
    1 3 2
    3 2 3
    3 4 5
    5 4 0
    4 5 8
    

    output

    3
    

    题解

    我们按照边出现的顺序依次向图中加边,这样就保证了出现时间是递增的,只需要考虑权值就行了。

    问题便转化为求出图上的最长上升子序列。

    类比最长上升子序列的线段树做法,记(f[i])表示以节点(i)为终点的最长上升路径长度,然后对图中每个点都维护一棵线段树,以边权作为区间,以(f)为值。每插入一条边在起点的线段数中统计答案,之后再把算出来的答案插入到终点对应的线段树中。

    代码

    #include<bits/stdc++.h>
    #define MAXN 100010
    #define lc t[rt].l
    #define rc t[rt].r
    namespace IO{
    	char buf[1<<15],*fs,*ft;
    	inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    	inline int qr(){
    		int x=0,rev=0,ch=gc();
    		while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=gc();}
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
    		return rev?-x:x;}
    }using namespace IO;
    using namespace std;
    struct Tree{int l,r,v;}t[MAXN<<5]; 
    int tot,root[MAXN],N,M,ans,f[MAXN];
    inline void Up(int rt){t[rt].v=max(t[lc].v,t[rc].v);}
    void Insert(int p,int l,int r,int &rt,int v){
    	if(!rt)rt=++tot;
    	if(l==r){t[rt].v=v;return;}
    	int mid=l+r>>1;
    	if(p<=mid)Insert(p,l,mid,lc,v);
    	else Insert(p,mid+1,r,rc,v);
    	Up(rt);
    }
    int Query(int L,int R,int l,int r,int rt){
    	if(L<=l&&R>=r)return t[rt].v;
    	int mid=l+r>>1,ret=0;
    	if(L<=mid&&lc)ret=Query(L,R,l,mid,lc);
    	if(R>mid&&rc)ret=max(ret,Query(L,R,mid+1,r,rc));
    	return ret; 
    }
    int x,y,z;
    int main(){
    	#ifndef ONLINE_JUDGE
    	freopen("cf960F.in","r",stdin);
    	freopen("cf960F.out","w",stdout);
    	#endif
    	N=qr();M=qr();
    	for(int i=1;i<=M;i++){
    		x=qr();y=qr();z=qr()+1;
    		f[y]=Query(1,z-1,1,100001,root[x])+1;
    		ans=max(ans,f[y]);
    		Insert(z,1,100001,root[y],f[y]);
    	}
    	printf("%d",ans);
    	return 0; 
    }
    
  • 相关阅读:
    并发编程(四)—— ThreadLocal源码分析及内存泄露预防
    并发编程(三)—— ReentrantLock的用法
    并发编程(二)—— CountDownLatch、CyclicBarrier和Semaphore
    并发编程(一)—— volatile关键字和 atomic包
    Java 多线程(四)—— 单例模式
    Java 多线程(三)—— 线程的生命周期及方法
    Java 多线程(二)—— 线程的同步
    星空雅梦
    星空雅梦
    星空雅梦
  • 原文地址:https://www.cnblogs.com/lrj998244353/p/8776100.html
Copyright © 2011-2022 走看看