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; 
}
posted @ 2018-04-10 07:51  lrj998244353  阅读(154)  评论(0编辑  收藏  举报
Live2D