图论(最短路/最小生成树/拓扑排序)
(网课题单)
A CF601A The Two Routes
一定有一种交通工具存在一条路径连接 ,于是对另一种交通工具跑最短路即可。
点击查看代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
int n,m,x,y,i,j,k,dis[405][405],sum;
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
memset(dis,0x3f,sizeof(dis));
for (i=1;i<=m;i++){
cin>>x>>y,dis[x][y]=1,dis[y][x]=1;
sum+=((x==1 && y==n) || (x==n && y==1));
}
if (sum!=0)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (dis[i][j]==1) dis[i][j]=dis[0][0];
else dis[i][j]=1;
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
return cout<<(dis[1][n]==dis[0][0]?-1:dis[1][n]),0;
}
B CF59E Shortest Path
BFS 的同时记录上一个经过的点即可。记录前驱的时候记录边,不是点。
启示:BFS 等算法同样是解决最短路问题的有效手段。
点击查看代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
int n,m,T,i,x,y,z;
struct Edge{
int to,nex,dis,pre,id;
}e[40005];
int h[3005],cnt;
void add_edge(int x,int y){
e[++cnt].to=y,e[cnt].nex=h[x],e[cnt].id=cnt,h[x]=cnt;
}
struct node{
int pre,now,step,id;
} ;
queue <node> Q;
map <pair<pair<int,int> ,int> ,bool> c;
void go(int x){
if (e[x].pre) go(e[x].pre);
cout<<' '<<e[x].to;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>T;
for (i=1;i<=m;i++)
cin>>x>>y,add_edge(x,y),add_edge(y,x);
for (i=1;i<=T;i++)
cin>>x>>y>>z,c[make_pair(make_pair(x,y),z)]=true;
Q.push(node{0,1,0,0});//pre now step id
while (!Q.empty()){
node x=Q.front();
Q.pop();
if (x.now==n){
cout<<x.step<<'\n'<<1;
return go(x.id),0;
}
for (i=h[x.now]; i; i=e[i].nex){
if (c[make_pair(make_pair(x.pre,x.now),e[i].to)]) continue;
if (e[i].dis) continue;
e[i].dis=x.step+1,e[i].pre=x.id;
Q.push((node){x.now,e[i].to,x.step+1,i});
}
}
return cout<<-1,0;
}
C CF1196F K-th Path
,从这方面入手,取最短的 条边,至多 个点做最短路,可以证明答案一定在其中。
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct Edge{int x,y,z;} e[200005];
bool cmp(Edge x,Edge y){return x.z<y.z;}
priority_queue <int,vector<int>,greater<int> > Q;
int n,m,k,i,j,tot,f[805][805],rnk[200005],vis[200005];
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for (i=1;i<=m;i++) cin>>e[i].x>>e[i].y>>e[i].z;
if (m>k) sort (e+1,e+1+m,cmp);
for (i=1;i<=min(m,k);i++) vis[e[i].x]=1,vis[e[i].y]=1;
for (i=1;i<=n;i++)
if (vis[i]) rnk[i]=(++tot);
memset(f,0x3f,sizeof(f));
for (i=1;i<=min(m,k);i++)
f[rnk[e[i].x]][rnk[e[i].y]]=f[rnk[e[i].y]][rnk[e[i].x]]=e[i].z;
for (int _=1;_<=tot;_++)
for (i=1;i<=tot;i++)
for (j=1;j<=tot;j++)
f[i][j]=min(f[i][j],f[i][_]+f[_][j]);
for (i=1;i<=tot;i++)
for (j=i+1;j<=tot;j++)
Q.push(f[i][j]);
for (i=1;i<k;i++) Q.pop();
return cout<<Q.top(),0;
}
D CF1307D Cow and Fields
从起点(结果记为 )、终点(结果记为 )做两遍最短路,按 给点集排序,贪心做一下。
E CF1242B 0-1 MST
答案为用 链接的联通块数量减一。用并查集维护(包括包含节点个数),枚举 ,根据每个联通块的大小和其与 相连的边为 的节点数即可判断该连痛块能否与 合并。
并查集一定要路径压缩 + 按秩合并。
可以证明(本蒟蒻不太会)时间复杂度为 。
F CF160D Edges in MST
不会思路 + 不会实现。
G CF1468J Road Reform & H [HAOI2006]聪明的猴子 & I [SCOI2005]繁忙的都市
最小生成树板子随便改一下。简单,懒得贴代码。
J 最短路(未知来源)
个点, 条边的有向图,求点 到点 的最短路(保证存在)。
。
正解:Dij
+ 配对堆。
普通堆优化:题目中为了防止读入时超时有随机边,注释即可。
K [HAOI2016]食物链
简单的 topo
加一点点数学,坑点在于:注意单独的一种孤立生物不算一条食物链。
L[SDOI2010]大陆争霸
被 LYH
吊打了。
最短路 + topo
(在做最短路的同时做一下 topo
),开三个数组分别表示最短路 dis
,topo
的结果 f
,答案 ans
(dis
和 f
的 )。
O ther:[JLOI2011] 飞行路线
经典分层图。gugu。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!