标签:有向图 return cstring 顺序 walk 重复 string 题目 div
题目大意:给你一张$n$个点$m$条边的带权有向图,可能有重边和自环。边会按照顺序给出。让你求出一条最长的路径,使得路径上的边满足边权和出现的时间严格递增。路径可以重复经过同一个点。
想办法把它转化成序列上的最长上升序列
我们如果按顺序加边,那么边做边求是符合边的出现时间递增的要求的
所以当给你一条边$a$->$b$边权为$c$时,我们要在合理的复杂度内查到到$a$点边权小于$c$的最长上升序列
然后用它去更新答案和到$b$边权小于等于$c$的最大值
这显然是个线段树,然后我们再搞个动态开点,完事
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define M 500010 5 #define ls ch[node][0] 6 #define rs ch[node][1] 7 using namespace std; 8 int read() 9 { 10 char ch=getchar();int x=0; 11 while(ch>‘9‘||ch<‘0‘) ch=getchar(); 12 while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); 13 return x; 14 } 15 int n,m,cnt,ans; 16 int root[M],val[M<<2],ch[M<<2][2]; 17 void insert(int &node,int l,int r,int k,int x) 18 { 19 if(!node) node=++cnt; 20 val[node]=max(val[node],x); 21 if(l==r) return; 22 int mid=(l+r)/2; 23 if(k<=mid) insert(ls,l,mid,k,x); 24 else insert(rs,mid+1,r,k,x); 25 } 26 int query(int node,int l,int r,int l1,int r1) 27 { 28 if(!node) return 0; 29 if(l1>r||r1<l) return 0; 30 if(l1<=l&&r1>=r) return val[node]; 31 int mid=(l+r)/2; 32 return max(query(ls,l,mid,l1,r1),query(rs,mid+1,r,l1,r1)); 33 } 34 int main() 35 { 36 n=read();m=read(); 37 for(int i=1;i<=m;i++) 38 { 39 int a=read(),b=read(),z=read()+1; 40 int x=query(root[a],1,100000,1,z-1)+1; 41 ans=max(ans,x); 42 insert(root[b],1,100001,z,x); 43 } 44 printf("%d",ans); 45 return 0; 46 }
标签:有向图 return cstring 顺序 walk 重复 string 题目 div
原文地址:https://www.cnblogs.com/Slrslr/p/9694766.html