F Pathwalks
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
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.
Input
The first line contains two integers n and m (1 ≤ n ≤ 100000,1 ≤ m ≤ 100000) — the number of vertices and edges in the graph, respectively.
m lines follows.
The i-th of these lines contains three space separated integers ai, bi and wi (1 ≤ ai, bi ≤ n, 0 ≤ wi ≤ 100000), denoting an edge from vertex ai to vertex bi having weight wi
Output
Print one integer in a single line — the maximum number of edges in the path.
Examples
inputCopy
3 3
3 1 3
1 2 1
2 3 2
outputCopy
2
inputCopy
5 5
1 3 2
3 2 3
3 4 5
5 4 0
4 5 8
outputCopy
3
Note
The answer for the first sample input is 2: . Note that you cannot traverse because edge appears earlier in the input than the other two edges and hence cannot be picked/traversed after either of the other two edges.
In the second sample, it’s optimal to pick 1-st, 3-rd and 5-th edges to get the optimal answer: .
题意:有n个顶点,m条边,可能存在重边和自环,每条边都有权值wi,要求一条经过边数最多且经过的边的权值是严格递增且经过的边的相对顺序与输入相对顺序一样的路径,输出路径长度
题解:这个相当于图上的最长上升子序列,仿照最长上升子序列可以使用线段树快速找到到达某个结点的最长路径长度,但是由于最长上升子序列的每个元素的顺序是固定的,所以只需要一个建一个线段树即可,而图中顶点的顺序是不定的,所以需要在每个结点上建立一棵线段树,显然直接建树会MLE,需要动态开点建线段树。又由于经过的边顺序需要按照输入的相对顺序,所以可以边输入边更新线段树边更新结果
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=1e5+5;
struct node{
int lson;
int rson;
int maxx;
}nod[maxn*70];
int root[maxn],tot;
int query(int rot,int l,int r,int l0,int r0){
if(!rot)return 0;
int mid=(l+r)>>1;
if(l>=l0&&r<=r0)return nod[rot].maxx;
int ac=0;
if(mid>=l0)ac=max(ac,query(nod[rot].lson,l,mid,l0,r0));
if(mid<r0)ac=max(query(nod[rot].rson,mid+1,r,l0,r0),ac);
return ac;
}
void pushup(int rot){
nod[rot].maxx=max(nod[nod[rot].lson].maxx,nod[nod[rot].rson].maxx);
}
void update(int &rot,int l,int r,int x,int val){
if(!rot)rot=++tot;
if(l==r){
nod[rot].maxx=max(nod[rot].maxx,val);
return;
}
int mid=(l+r)>>1;
if(mid>=x)update(nod[rot].lson,l,mid,x,val);
else update(nod[rot].rson,mid+1,r,x,val);
pushup(rot);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
int ans=0;
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int ac=query(root[a],1,maxn-1,1,c)+1;
ans=max(ans,ac);
update(root[b],1,maxn-1,c+1,ac);
}
printf("%d\n",ans);
return 0;
}