题目:

思路:
这道题是一对多和多对一,一对多的问题笔记好解决,一对多的是第一次碰到。因为这道题里给的是有向图,所以不妨把所有的路反向存一遍,比如a->b存成b->a,然后就又变成了一对多问题。
#include<cstdio>
#include <iostream>
#include<cstring>
#include<algorithm>
#include <vector>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=1111;
struct node
{
int x,dis;
bool operator >(const node &a)const
{
if(dis==a.dis) return x<a.x;
return dis>a.dis;
}
};
priority_queue <node,vector<node>,greater<node>> q,q1;
typedef pair<int,int> pii;
vector <pii> e[100*maxn],e1[100*maxn];
int n,m,s,day[maxn],dis[maxn];
bool vis[maxn];
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,w;
cin>>x>>y>>w;
if(x==y) continue;
e[x].push_back({y,w});
e1[y].push_back({x,w});
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
q.push({1,0});
while(!q.empty())
{
int temp=q.top().x;
q.pop();
if(vis[temp]) continue;
vis[temp]=1; //cout<<"!!"<<temp<<endl;
for(auto to:e[temp])
{
dis[to.first]=min(dis[to.first],dis[temp]+to.second);
//cout<<"to.first="<<to.first<<" "<<"dis[to.first]"<<dis[to.first]<<endl;
q.push({to.first,dis[to.first]});
}
}
int ans=0;
for(int i=1;i<=n;i++) ans+=dis[i];
for(int i=1;i<=n;i++) vis[i]=0;
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
q1.push({1,0});
//for(auto to:e1[1]) cout<<"to.first="<<to.first<<" "<<"dis[to.first]"<<dis[to.first]<<endl;
while(!q1.empty())
{
int temp=q1.top().x;
q1.pop();
if(vis[temp]) continue;
vis[temp]=1; //cout<<"!!"<<temp<<endl;
for(auto to:e1[temp])
{
//cout<<"to.first="<<to.first<<" "<<"dis[to.first]"<<dis[to.first]<<endl;
dis[to.first]=min(dis[to.first],dis[temp]+to.second);
q1.push({to.first,dis[to.first]});
}
}
for(int i=1;i<=n;i++) ans+=dis[i];
cout<<ans<<endl;
return 0;
}
该博客讲解了如何解决一个涉及有向图的一对多问题,通过反向存储边并转换为一对多形式,使用优先队列求解最短路径。作者详细展示了从两个起点到所有节点的最短距离计算过程。
594

被折叠的 条评论
为什么被折叠?



