Living-Dream 系列笔记 第37期
T1
令 \(dp_i\) 表示以 \(i\) 结尾的最大食物链条数。
有转移方程:
\[dp_i=\max(dp_i,dp_i+dp_j)(j \in \operatorname{son} i)
\]
按拓扑序转移即可。
#include<bits/stdc++.h> #define int long long using namespace std; int n,m,maxi,ans; int dp[5031],in[5031],out[5031]; vector<int> G[500031]; const int MOD=80112002; void topo(){ queue<int> q; for(int i=1;i<=n;i++) if(!in[i]) q.push(i),dp[i]=1; while(!q.empty()){ int cur=q.front(); q.pop(); for(int i:G[cur]){ in[i]--,dp[i]=max(dp[i],dp[cur]+dp[i]),dp[i]%=MOD; if(!in[i]) q.push(i); } } } signed main(){ cin>>n>>m; for(int i=1,u,v;i<=m;i++) cin>>u>>v,G[u].push_back(v),in[v]++,out[u]++; topo(); for(int i=1;i<=n;i++) if(!out[i]) ans=(ans+dp[i])%MOD; cout<<ans%MOD; return 0; }
T2
令 \(dp_i\) 表示以 \(i\) 结尾的最多游览的城市数量。
有转移方程:
\[dp_i=\max(dp_i,dp_j+1)(j \in \operatorname{son} i)
\]
按拓扑序转移即可。
#include<bits/stdc++.h> #define int long long using namespace std; int n,m,maxi,ans; int dp[100031],in[100031]; vector<int> G[200031]; const int MOD=80112002; void topo(){ queue<int> q; for(int i=1;i<=n;dp[i]=1,i++) if(!in[i]) q.push(i); while(!q.empty()){ int cur=q.front(); q.pop(); for(int i:G[cur]){ in[i]--,dp[i]=max(dp[i],dp[cur]+1); if(!in[i]) q.push(i); } } } signed main(){ cin>>n>>m; for(int i=1,u,v;i<=m;i++) cin>>u>>v,G[u].push_back(v),in[v]++; topo(); for(int i=1;i<=n;i++) cout<<dp[i]<<'\n'; return 0; }
习题 T1
有点意思的一道题。
若 \(m=n-1\),此时原图呈树,直接 排序 + dfs 求解即可。
若 \(m=n\),此时原图呈基环树,考虑运用 toposort 找环(无向图节点度数为 \(1\) 则入队),
断环成树,依旧仿照上面做即可。正确性显然(可以通过样例理解)。
这样的时间复杂度有点高且实现也有些困难,
因此我们也可以不找环,直接枚举所有边选择断开哪条即可。
#include<bits/stdc++.h> #define int long long using namespace std; int n,m; vector<int> G[10031]; int tot,totp; int ans[5031],tans[5031]; int vis[5031]; struct E{ int from,to; }e[10031]; namespace sol1{ void dfs(int x,int f){ if(vis[x]) return; ans[++tot]=x,vis[x]=1; for(int i:G[x]) if(i!=f) dfs(i,x); } void solve(){ for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end()); dfs(1,-1); for(int i=1;i<=n;i++) cout<<ans[i]<<' '; } } namespace sol2{ void dfs(int x,int f,int u,int v){ if(vis[x]) return; tans[++tot]=x,vis[x]=1; for(int i:G[x]) if(i!=f&&(!(x==u&&i==v))&&(!(x==v&&i==u))) dfs(i,x,u,v); } bool cmp(int *a,int *b){ for(int i=1;i<=n;i++){ if(a[i]<b[i]) return 1; if(a[i]>b[i]) return 0; } return 0; } void solve(){ for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end()); bool f=1; for(int i=1;i<=m;i++){ tot=0,memset(vis,0,sizeof(vis)); dfs(1,-1,e[i].from,e[i].to); if(f) memcpy(ans,tans,sizeof(ans)),f=0; if(cmp(tans,ans)&&tot==n) memcpy(ans,tans,sizeof(ans)); } for(int i=1;i<=n;i++) cout<<ans[i]<<' '; } } signed main(){ cin>>n>>m; for(int i=1,u,v;i<=m;i++) cin>>u>>v, G[u].push_back(v),G[v].push_back(u), e[i].from=u,e[i].to=v; if(m==n-1) sol1::solve(); else sol2::solve(); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现