AT_abc335_e
说句闲话
场上一开始还读错题,耽误好多时间。后来想到正解,但怎么写也写不对,吃了巨大罚时,菜死了。所以跑来写写题解水经验总结一下。
题意简述
给定一个
题目解析
我一开始的朴素思路是直接 dp。具体地,设
发现既然要走单调不降的路径,那么我们可以对每一条无向边定向,即小的连向大的。那么相等权值怎么办呢?考虑这些点不会多次影响答案,所以把这些点缩成一个点即可。这样以后满足偏序关系,所以新图是一个有向无环图(DAG),问题转化成最长链,直接在图上拓扑就行了。
还是有点细节的,具体见代码。我直接用 dfs 缩点了,懒得写 tarjan。
参考代码
马蜂不好看的话请各位大佬轻喷 qwq。
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define endl '\n'
#define eb emplace_back
#define N 200005
int n,m;
int a[N],scc[N],du[N],dis[N],cnt;
vector<int> g[N],e[N];
queue<int> q;
void dfs(int u){
scc[u]=cnt;
for(auto v:g[u]) if(!scc[v]&&a[u]==a[v]) dfs(v);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
memset(dis,-0x3f,sizeof(dis));
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=m;++i){
int u,v;
cin>>u>>v;
if(a[u]<=a[v]) g[u].eb(v);
if(a[v]<=a[u]) g[v].eb(u);
}
for(int i=1;i<=n;++i){
if(!scc[i]){
cnt++;
dfs(i);
}
}
for(int i=1;i<=n;++i){
for(auto j:g[i]){
if(scc[i]!=scc[j]){
e[scc[i]].eb(scc[j]);
du[scc[j]]++;
}
}
}
dis[scc[1]]=1;
for(int i=1;i<=cnt;++i) if(!du[i]) q.push(i);
while(!q.empty()){
int u=q.front();
q.pop();
for(auto v:e[u]){
if(!(--du[v])) q.push(v);
dis[v]=max(dis[v],dis[u]+1);
}
}
cout<<max(0,dis[scc[n]])<<endl;
return 0;
}
完结撒花!(请管理通过,拜托啦。)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步