P3008 [USACO11JAN]Roads and Planes G
P3008 [USACO11JAN]Roads and Planes G
思路
按照分连通块的方法进行计算,并且如果不是本连通块的点,不能在现在的本次dfs中求解最小值。要一个一个的联通快进行标记。
/* 不能直接走disj的话,缩点的思想很重要 首先尽量不要使用spfa进行走图,可能会卡 对道路进行求连通块,对航线求度数,然后利用topsort进行求解连通块 一次只对一个集合里面的点进行更新 */ #include <bits/stdc++.h> using namespace std; const int N=25005,inf=2e9; using pii=pair<int,int>; vector<pii>v1[N],v2[N]; vector<int>v[N]; int id[N],in[N],dis[N]; bool vis[N]; void dfs(int now,int num) { id[now]=num; v[num].push_back(now); for(auto [to,wi]:v1[now]) if(id[to]==0)dfs(to,num); } int main() { int n,m1,m2,st; cin>>n>>m1>>m2>>st; for(int i=1;i<=m1;i++) { int x,y,wi; cin>>x>>y>>wi; v1[x].push_back({y,wi}); v1[y].push_back({x,wi}); } for(int i=1;i<=m2;i++) { int x,y,wi; cin>>x>>y>>wi; v2[x].push_back({y,wi}); } int cnt=0; for(int i=1;i<=n;i++)if(id[i]==0)dfs(i,++cnt); for(int i=1;i<=n;i++) { dis[i]=(i==st?0:inf); for(auto [to,wi]:v2[i])in[id[to]]++; } queue<int>q; for(int i=1;i<=cnt;i++) if(in[i]==0)q.push(i); while(!q.empty()) { int t=q.front();q.pop(); priority_queue<pii>pq; for(auto to:v[t])if(dis[to]<inf)pq.push({-dis[to],to}); while(!pq.empty()) { auto [w,now]=pq.top();pq.pop();w=-w; if(vis[now])continue;vis[now]=1; for(auto [to,wi]:v1[now]) if(dis[to]>w+wi) { dis[to]=w+wi; pq.push({-dis[to],to}); } for(auto [to,wi]:v2[now]) if(dis[to]>w+wi)dis[to]=w+wi; } for(auto now:v[t]) for(auto [to,wi]:v2[now]) if(--in[id[to]]==0)q.push(id[to]); } for(int i=1;i<=n;i++) { if(dis[i]==inf)cout<<"NO PATH\n"; else cout<<dis[i]<<endl; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现