[CF459E]Pashmak and Graph

做题时间:2021.03.15

\(【题目描述】\)

给出一张\(N(N \leq 10^5)\)个点的有向图,在图中找出最长的一条路径,使得路径中的边不重复且每一条边的边权都必须大于上一条边的边权。

\(【输入样例】\)

6 7
1 2 1
3 2 5
2 4 2
2 5 2
2 6 9
5 4 3
4 3 4

\(【输出样例】\)

6

\(【考点】\)

动态规划

\(【做法】\)

这道题目可以转化为在图上进行求最长不下降子序列的问题。定义\(f[i]\)表示以点\(i\)为结尾的路径的最长长度。为了维护DP的后效性,因此以边权为顺序进行枚举(边权小的必定会在边权大的之前便利)。

另外需注意,当两条边\([u,v]\)\([v,w]\)边权相等时,如果先便利\([u,v]\),更新\(f[v]\)的话,那么\([v,w]\)的答案就会接着被\(f[v]\)更新到,即出现了\(u\rightarrow v\rightarrow w\)的情况,与题目不符。此时应当用另一数组\(ff[i]\)将当前所有连接相等边权的点全部更新后,再赋值给\(f[i]\)

\(【代码】\)

#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<queue>
using namespace std;
const int N=3e5+50;
struct point{
	int u,v,w,val;
}g[N];
int f[N],ff[N];
int n,m;
bool cmp(point p,point q){return p.w<q.w;}
inline int Max(int a,int b){return a>b?a:b;}
int main()
{
	scanf("%d%d",&n,&m);
	int u,v,w;
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);
		g[i]=(point){u,v,w};
	}
	sort(g+1,g+1+m,cmp);
	int k=1;
	for(int i=1;i<=m;i=k+1){
		k=i;
		while(g[k].w==g[k+1].w) k++;//获取所有边权相等的点
		
		for(int j=i;j<=k;j++) ff[g[j].v]=Max(ff[g[j].v],f[g[j].u]+1);//先赋值给ff
		for(int j=i;j<=k;j++) f[g[j].v]=Max(f[g[j].v],ff[g[j].v]);//之后赋值给f
	}
	int ans=0;
	for(int i=1;i<=n;i++) ans=Max(ans,f[i]);
	printf("%d\n",ans);
	return 0;
}
posted @ 2021-03-16 14:02  lxzy  阅读(72)  评论(0)    收藏  举报