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;
}