原题:1087. All Roads Lead to Rome (30)
解题思路:
用最短路径算法求出所有最短路径,再用dfs方法探索每条路径,选出符合条件的路径即可。
代码如下:
#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
#include<cstring>
using namespace std;
const int maxn = 200+5;
const int INF = 0x3fffffff;
int happiness[maxn];
vector<string> name;
map<string, int> IDcache;
//数字化
int ID(string s)
{
if(IDcache.count(s)) return IDcache[s];
name.push_back(s);
return IDcache[s] = name.size()-1;
}
int n, k, st, des, ansNum;
int G[maxn][maxn];
int vis[maxn];
int d[maxn];
vector<int> p[maxn]; //保存最短路径的父节点
void Dijkstra(int s)
{
fill(vis, vis+maxn, 0);
fill(d, d+maxn, INF);
d[s] = 0;
for(;;)
{
int u = -1, MIN = INF;
for(int i = 0; i < n; i++)
{
if(!vis[i] && d[i] < MIN)
{
MIN = d[i];
u = i;
}
}
if(u == -1) break;
vis[u] = 1;
for(int v = 0; v < n; v++)
{
if(!G[u][v]) continue;
if(d[v] > d[u] + G[u][v])
{
d[v] = d[u] + G[u][v];
p[v].clear();
p[v].push_back(u);
}
else if(d[v] == d[u] + G[u][v])
{
p[v].push_back(u);
}
}
}
}
int ansMaxH, ansMaxC;
vector<int> ans, tmp;
void dfs(int maxH, int maxC, int d)
{
if(d == st) //探索回起点
{
ansNum++;
if(maxH > ansMaxH)
{
ansMaxH = maxH;
ansMaxC = maxC;
tmp.push_back(d);
ans = tmp;
tmp.pop_back();
}
else if(maxH == ansMaxH)
{
if(ansMaxH * maxC < maxH * ansMaxC)
{
ansMaxH = maxH;
ansMaxC = maxC;
tmp.push_back(d);
ans = tmp;
tmp.pop_back();
}
}
return;
}
tmp.push_back(d);
for(int i = 0; i < p[d].size(); i++)
{
dfs(maxH+happiness[d], maxC + 1, p[d][i]);
}
tmp.pop_back();
}
int main()
{
while(scanf("%d%d", &n, &k) == 2)
{
memset(G, 0, sizeof(G));
char nam[5];
scanf("%s", nam);
string s(nam);
st = ID(s); happiness[st] = 0;
for(int i = 1; i < n; i++)
{
int hap;
scanf("%s%d", nam, &hap);
s = nam;
if(s == "ROM") des = ID(s);
happiness[ID(s)] = hap;
}
for(int i = 0; i < k; i++)
{
char nam1[5], nam2[5];
int cost;
scanf("%s%s%d", nam1, nam2, &cost);
string s1(nam1), s2(nam2);
G[ID(s1)][ID(s2)] = cost;
G[ID(s2)][ID(s1)] = cost;
}
ansNum = 0;
Dijkstra(st);
ansMaxC = 0;
ansMaxH = 0;
dfs(0, 0, des);
printf("%d %d %d %d\n", ansNum, d[des], ansMaxH, ansMaxH/ansMaxC);
for(int i = ans.size() - 1; i >= 0; i--)
if(i != ans.size() - 1) printf("->%s", name[ans[i]].c_str());
else printf("%s", name[ans[i]].c_str());
printf("\n");
}
return 0;
}