uva117 最短路径

uva117题,题目意思是:对于输入的一行字母,首字母和尾字母分别代表顶点,它们之间的距离为字符串长度。要求遍历每条线段至少要走的距离。

因为最多只有两个度为奇数的点,如果度均为偶数,则是欧拉回路,输出所有边长,若有奇数,则还要加上两个奇点间的最短路径。

关于最短路径,用的是Bellman-Ford算法,松弛number-1次,就能找到单点到任意点的最短距离。


本题将顶点数记为number,外循环指循环number次,内循环是遍历存放边的线性表

由于字母共有26个,用vector<> t[26] 代表从与每个点相邻的顶点及边长

代码:

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
using namespace std;
#define Infinit 10000
struct street{
 int u,v;
 int len;
 street(int x,int y,int z) : u(x),v(y),len(z){}
};
vector<street> v[26];  //26个字母  0-a 1-b 2-c ……25-z
int odd[2];   //两个奇数点
int number = 0;   //the number of streets
int dis[26][26];  //dis[i][j]:the shorttest path from i to j 
bool isodd(){
 int k=0;
 for(int i=0;i<26;i++){
  if(!v[i].empty()) {
   number++;
  } 
  if(v[i].size()%2==1)  odd[k++]=i;
 }
 if(k==2) return false; 
 return true;
}
int BellMan(int start,int end){
 for(int i=0;i<26;i++){
  for(int j=0;j<26;j++){
   dis[i][j]=Infinit;
  }
 }
 for(int i=0;i<26;i++){
  for(int j=0;j<v[i].size();j++){
   dis[i][v[i][j].v]=v[i][j].len;
   //cout<<i<<"->"<<v[i][j].v<<"="<<dis[i][v[i][j].v]<<endl;
  }
 }
 for(int k=0;k<number;k++){
  for(int i=0;i<26;i++){
   for(int j=0;j<v[i].size();j++){
    if(dis[start][i] + v[i][j].len < dis[start][v[i][j].v])
     dis[start][v[i][j].v] = dis[start][i] + v[i][j].len;
   }
  }
 }
 return dis[start][end];
}
int Computing(){
 if(isodd())  return 0;  //无奇数度
 return BellMan(odd[0],odd[1]);
}

int main(){
 string str;
 int sum = 0;
 while(cin>>str){
  if(str=="deadend") {
   int shorttest = Computing();
   cout<<sum+shorttest<<endl;
   for(int i=0;i<26;i++) v[i].clear();
   sum = 0,number = 0;
   continue;
  }
  v[int(str[0]-'a')].push_back( street( int(str[0]-'a'),
    int(str[str.length()-1]-'a'),str.length() ) );
  v[int(str[str.length()-1]-'a')].push_back( street( int(str[str.length()-1]-'a'),
    int(str[0]-'a'),str.length() ) );
  sum += str.length();  
 }
 return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值