【题目描述】
【思路】
如果是有向图,那么可以把边按照从小到大排序,然后设
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;
}