这题和ZOJ 2008做法一样,求两次最短路,一次是s到各个点,一次是把图反向后s到各个点.
两个结果相加就是答案.
用spfa或者dijkstra都可以.
#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <map>
using namespace std;
const int maxn=110;
struct edge{
int v,w,next;
}e[2][30010];
struct node{
int i,v;
node(int ii=0,int vv=0):i(ii),v(vv){}
bool operator<(const node &rhs)const{
return v>rhs.v;
}
};
int head[2][maxn],dis[maxn],vis[maxn],N,C,R;
map<string,int>sToNum,cnt;
char buf1[20],buf2[20],buf3[20];
string start;
void addEdge(int eIdx,int idx,int u,int v,int w){
e[idx][eIdx].v=v;
e[idx][eIdx].w=w;
e[idx][eIdx].next=head[idx][u];
head[idx][u]=eIdx;
}
int dijstra(int idx){
priority_queue<node>q;
q.push(node(sToNum[start],0));
memset(dis,0X7F7F7F7F,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[sToNum[start]]=0;
while (q.size())
{
node t=q.top();
q.pop();
if(vis[t.i])continue;
vis[t.i]=1;
for (int ne=head[idx][t.i];ne!=-1;ne=e[idx][ne].next){
int v=e[idx][ne].v,w=e[idx][ne].w;
if(dis[v]>dis[t.i]+w&&!vis[v]){
dis[v]=dis[t.i]+w;
q.push(node(v,dis[v]));
}
}
}
int ans=0;
map<string,int>::iterator it=cnt.begin();
for (;it!=cnt.end();++it){
ans+=dis[sToNum[it->first]]*it->second;
}
return ans;
}
int spfa(int idx){
queue<int>q;
q.push(sToNum[start]);
memset(dis,0X7F,sizeof(dis));
memset(vis,0,sizeof(vis));
vis[sToNum[start]]=1;
dis[sToNum[start]]=0;
while (q.size())
{
int t=q.front();
q.pop();
vis[t]=0;
for (int ne=head[idx][t];ne!=-1;ne=e[idx][ne].next){
int v=e[idx][ne].v,w=e[idx][ne].w;
if(dis[v]>dis[t]+w){
dis[v]=dis[t]+w;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
int ans=0;
map<string,int>::iterator it=cnt.begin();
for (;it!=cnt.end();++it){
ans+=dis[sToNum[it->first]]*it->second;
}
return ans;
}
int main(){
int cas=1;
while (scanf("%d%d%d",&N,&C,&R))
{
if(!N&&!R&&!C)break;
int eIdx=0,pIdx=0;
sToNum.clear(),cnt.clear();
for (int i=0;i<N;++i){
head[0][i]=head[1][i]=-1;
}
cin>>start;
while (C--){
scanf("%s",buf1);
cnt[string(buf1)]++;
}
for (int i=0;i<R;++i)
{
int v;
scanf("%s%s%s",buf1,buf2,buf3);
string s1=buf1,s2=buf3;
if(sToNum.find(s1)==sToNum.end()){
sToNum[s1]=pIdx++;
}
if(sToNum.find(s2)==sToNum.end()){
sToNum[s2]=pIdx++;
}
char garbage[10];
sscanf(buf2,"%[^1-9]%d",garbage,&v);
if(buf2[0]=='<'){
addEdge(eIdx,0,sToNum[s2],sToNum[s1],v);//a->b
addEdge(eIdx,1,sToNum[s1],sToNum[s2],v);//b->a(添加反向边)
eIdx++;
}
if(buf2[strlen(buf2)-1]=='>'){
addEdge(eIdx,0,sToNum[s1],sToNum[s2],v);//a->b
addEdge(eIdx,1,sToNum[s2],sToNum[s1],v);//b->a
eIdx++;
}
}
printf("%d. %d\n",cas++,spfa(0)+spfa(1));
}
return 0;
}