思路:从起点跑一遍Dij,把从起点到各目标点的dist相加;再从各目标点分别跑Dij,把从目标点到起点的dist相加,即是答案。
注意:
1. 输入处理比较繁,耐心写就好。
2. 0<N<100, 0<=C<1000 会有重边,用邻接矩阵存图。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N=105,M=10005;
int g[N][N];
int dist[N];
bool st[N];
int n,c,r;
string str[1005];
void Dij(int s){
memset(dist,0x3f,sizeof dist);
dist[s]=0;
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,s});
while(heap.size()){
auto t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=1;i<=n;++i){
if(distance+g[ver][i]<dist[i]){
dist[i]=distance+g[ver][i];
heap.push({dist[i],i});//
}
}
}
}
int main(){
int Case=0;
while( scanf("%d%d%d",&n,&c,&r)!=EOF && n ){
memset(g,0x3f,sizeof g);
memset(dist,0,sizeof dist);
memset(st,0,sizeof st);
int tot=1;
string cpn;
cin>>cpn;
map<string,int>mp;
mp[cpn]=1;
for(int i=0;i<c;++i) cin>>str[i];
for(int i=0;i<r;++i){
string s1,s2,s3;
cin>>s1>>s2>>s3;
int l=s2.size();
int w=0;
for(int i=0;i<l;++i) if( isdigit(s2[i]) ) w=w*10+s2[i]-'0';
if(!mp[s1]) mp[s1] = ++tot;
if(!mp[s3]) mp[s3] = ++tot;
if(s2[0]=='<'&&s2[l-1]=='-') g[mp[s3]][mp[s1]]=min(g[mp[s3]][mp[s1]],w);//add(mp[s3],mp[s1],w);
else if(s2[0]=='<'&&s2[l-1]=='>') g[mp[s1]][mp[s3]]=min(g[mp[s1]][mp[s3]],w),g[mp[s3]][mp[s1]]=min(g[mp[s3]][mp[s1]],w);//add(mp[s1],mp[s3],w),add(mp[s3],mp[s1],w);
else if(s2[0]=='-'&&s2[l-1]=='>') g[mp[s1]][mp[s3]]=min(g[mp[s1]][mp[s3]],w);//add(mp[s1],mp[s3],w);
}
Dij(1);
long long ans=0;
for(int i=0;i<c;++i){
ans+=dist[mp[str[i]]];
}
for(int i=0;i<c;++i) {
memset(dist,0,sizeof dist);
memset(st,0,sizeof st);
Dij(mp[str[i]]);
ans+=dist[1];
}
printf("%d. %lld\n",++Case,ans);
}
}
SPFA、Floyd有空再写