M. Moving Both Hands(反向图+Dijkstra)
Problem - 1725M - Codeforces
题目大意:给你一个有向图,起始点在1,问起始点分别与另外n-1个 点相遇的最短时间,无法相遇输出-1。
思路:反向建图,第一层建原图,第二层建反向图,两层中对应点之间连接一条权值为0的边,最终答案为第一层的1号点到第二层i号点的最短路。
原理:由于两点均可移动,所以一定存在点p,使得s->p,p<-t,此时在第二层中建反向图p<-t转换成p->t,相当于直接从起点s跑单源最短路,而两层间对应点间全值为0的边,表示当前点为相遇点。
Code:
vector<PII> e[500010];void solve()
{int n,m;cin>>n>>m;while(m--){int a,b,c;cin>>a>>b>>c;e[a].push_back({b,c});e[n+b].push_back({n+a,c});}for(int i=1;i<=n;i++) e[i].push_back({i+n,0});vector<int> dist(n*2+5,1e18);dist[1]=0;vector<bool> st(n*2+5,false);priority_queue<PII,vector<PII>,greater<PII>> heap;heap.push({0,1});while(heap.size()){auto [d,u]=heap.top();heap.pop();if(st[u]) continue;st[u]=true;for(auto [v,w]:e[u]){if(dist[v]>d+w){dist[v]=d+w;heap.push({dist[v],v});}}}for(int i=2;i<=n;i++){if(dist[i+n]==1e18) cout<<-1<<' ';else cout<<dist[i+n]<<' ';}
}signed main()
{ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);int t;//cin>>t;t=1;while(t--) solve();
}