51Nod 1274 - 最长递增路径(DP)

【题目描述】
在这里插入图片描述
【思路】
如果是有向图,那么可以把边按照从小到大排序,然后设 d p [ i ] dp[i] dp[i] i i i 为终点的最长距离。有 d p [ u ] = m a x { d p [ u ] , d p [ v ] + 1 ∣ ( u , v ) ∈ E } dp[u]=max\{dp[u],dp[v]+1|(u,v)\in E\} dp[u]=max{dp[u],dp[v]+1(u,v)E}

而在无向图中,对于无向边 ( u , v ) (u,v) (u,v)
d p [ u ] = m a x { d p [ u ] , d p [ v ] + 1 } dp[u]=max\{dp[u],dp[v]+1\} dp[u]=max{dp[u],dp[v]+1}
d p [ v ] = m a x { d p [ v ] , d p [ u ] + 1 } dp[v]=max\{dp[v],dp[u]+1\} dp[v]=max{dp[v],dp[u]+1}
因为 d p dp dp 是一个数组,两个状态转移方程的先后顺序会有所影响。
所以另外用一个数组 t m p tmp tmp t m p [ i ] tmp[i] tmp[i] 记录上一次更新后时候的 d p [ i ] dp[i] dp[i]
那么就有:
d p [ u ] = m a x { d p [ u ] , t m p [ v ] + 1 } dp[u]=max\{dp[u],tmp[v]+1\} dp[u]=max{dp[u],tmp[v]+1}
d p [ v ] = m a x { d p [ v ] , t m p [ u ] + 1 } dp[v]=max\{dp[v],tmp[u]+1\} dp[v]=max{dp[v],tmp[u]+1}
对边权升序排序,对于每一种权值进行统一处理

#include<bits/stdc++.h>
using namespace std;

const int maxn=50005;

struct Edge{
	int from,to,dist;
	Edge(int f=0,int t=0,int d=0):from(f),to(t),dist(d){}
	bool operator<(const Edge& e)const{
		return dist<e.dist;
	}
};

int n,m;
Edge edges[maxn];
int tmp[maxn],dp[maxn];

int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;++i){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		edges[i]=Edge(u,v,w);
	}
	sort(edges,edges+m);
	int st=0;
	for(int i=0;i<m;++i){
		if(i==m-1 || edges[i].dist<edges[i+1].dist){
			for(int j=st;j<=i;++j){
				int u=edges[j].from;
				int v=edges[j].to;
				tmp[u]=dp[u];
				tmp[v]=dp[v];
			}
			for(int j=st;j<=i;++j){
				int u=edges[j].from;
				int v=edges[j].to;
				dp[u]=max(dp[u],tmp[v]+1);
				dp[v]=max(dp[v],tmp[u]+1);
			}
			st=i+1;
		}
	}
	int ans=0;
	for(int i=0;i<n;++i) ans=max(ans,dp[i]);
	printf("%d\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值