- 并查集专题
T5
- @ 2025-8-20 17:39:19
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 +10;
int n, m, a[N], fa[N], dp[N];
vector<int> g[N]; //邻接表
vector<pair<int, int> > edges; //存原始边
int find(int x)
{
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
bool cmp(int x, int y)
{
return a[find(x)] < a[find(y)];
}
void merge(int u, int v)
{
int fu = find(u), fv = find(v);
if(fu != fv) fa[fv] = fu;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
fa[i] = i;
}
//缩点
for(int i = 0; i < m; i++)
{
int u, v;
cin >> u >> v;
edges.push_back({u, v});
if(a[u] == a[v]) merge(u, v);
}
//建图
for(auto [u, v] : edges) {
int fu = find(u), fv = find(v);
if(a[fu] < a[fv]) g[fu].push_back(fv);
else if(a[fu] > a[fv]) g[fv].push_back(fu);
}
memset(dp, -1, sizeof dp);
dp[find(1)] = 1; //此时起点价值初始化为1
//dp的顺序
vector<int> nodes;
for(int i = 1; i <= n; i++) nodes.push_back(i);
sort(nodes.begin(), nodes.end(), cmp);
for(int u : nodes) {
int fu = find(u);
if(dp[fu] == -1) continue;
for(int v : g[fu]) {
int fv = find(v);
if(a[fu] < a[fv]) dp[fv] = max(dp[fv], dp[fu] + 1);
else dp[fv] = max(dp[fv], dp[fu]);
}
}
cout << max(0, dp[find(n)]) << endl;
return 0;
}
/*
1.经过缩点后:DAG图
2.有了拓扑序 A B C D E
以第i个点为终点的最大价值 f[i]
f[i]: 表示从顶点1到节点i的最大价值
v -> u
a[v] = a[u]: f[u] = max(f[v], f[u])
a[v] < a[u]: f[u] = max(f[u], f[v] + 1)
*/
0 条评论
目前还没有评论...