[省选 2021] 图函数
直接想没有思路的时候看怎么转化题意。
先手动模拟一次,发现当函数执行到 时, 自己就被删掉了,所以 不会变化了。同时,到 的时候, 都被删了,所以只能经过 的点。所以翻译下 就是图中满足 的 的个数,其中定义 表示 可以通过 的点互达。()
而所有时候我们需要的都是 ,因此 的条件可以去掉,转为求 。
先考虑第一问(图完整)。观察到 为一种连通性关系,floyd 是用来求解此类问题的,再考虑如何解决所经点限制,floyd 有专门的一个循环来枚举所经点,当外层 k
从大到小枚举并在内层两个循环中加一些 if
就容易满足。
再考虑求出每个图,由于是边的有无影响了连通性,重要一点在于想到转化为(用 floyd)维护 一个点能到另一个点的最早时间,即最大的 使加入第 条边后一个点可以到达另一个点。
启示:
- 有关连通性的题目可以想 floyd
- 每次只改动一条边或类似情况,有时间轴思想、整体处理
- 图中类似于函数的叙述,力求破译其本质
轻微卡常即可写出代码。复杂度 。
复制#include <bits/stdc++.h> using namespace std; const int N=1005,M=2e5+5; int n,m,f[N][N],ans[M]; inline int read(){ register char ch=getchar();register int x=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x; } void print(int x){ if(x/10)print(x/10); putchar(x%10+48); } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++)f[i][i]=m+1; for(int i=1,u,v;i<=m;i++)u=read(),v=read(),f[u][v]=i; for(int k=n;k;k--){ for(int i=1;i<=k;i++) for(int j=1;j<=n;j++){ if(f[i][k]&&f[k][j])f[i][j]=max(f[i][j],min(f[i][k],f[k][j])); } for(int i=k+1;i<=n;i++) for(int j=1;j<=k;j++){ if(f[i][k]&&f[k][j])f[i][j]=max(f[i][j],min(f[i][k],f[k][j])); } } for(int i=1;i<=n;i++)for(int j=i;j<=n;j++)ans[min(f[i][j],f[j][i])]++; for(int i=m;i;i--)ans[i]+=ans[i+1]; for(int i=1;i<=m+1;i++)print(ans[i]),putchar(' '); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库