题目
题意: 给定n个点,m条边。每个点有对应的点权。输出对应的最短路。如果有多条最短路,则输出经过点数最多的路径,若仍有多条,输出点权和最大的路径。而且输入的点是以字符串形式给出的,要拿map映射一下,不过还好n很小,n <= 200.
思路: 拿Dij跑一下即可,感觉写起来很麻烦,也可能我写麻烦了。
时间复杂度: O((n+m)logn + mlogm)
代码:
#include<bits/stdc++.h>
using namespace std;
#define mem(a,x) memset(a,x,sizeof(a))
typedef pair<int,int> PII;
const int N = 202;
map<string,int> mp;
map<int,string> mp2;
int dist[N];
bool vis[N];
int cnt[N]; //最短路条数
int num[N]; //点数
int sum[N]; //点权和
int a[N];
int h[N],e[N<<1],ne[N<<1],w[N<<1],idx = 0;
int pre[N];
int n,m,k,T;
string st,ed;
//最短路、点数、点权
int tot = 0;
void add(int a,int b,int c)
{
e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx++;
}
void Dij(int S)
{
mem(vis,false);
mem(dist,0x3f);
dist[S] = 0;
priority_queue<PII,vector<PII>,greater<PII> > q;
q.push({0,S});
cnt[S] = 1;
while(q.size())
{
PII tmp = q.top(); q.pop();
int u = tmp.second,dis = tmp.first;
if(dis != dist[u]) continue;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(dist[j] > dist[u] + w[i])
{
dist[j] = dist[u] + w[i];
cnt[j] = cnt[u];
num[j] = num[u] + 1;
sum[j] = sum[u] + a[j];
// cout<<j<<":"<<a[j]<<endl;
// cout<<j<<":"<<sum[j]<<endl;
pre[j] = u;
q.push({dist[j],j});
}
else if(dist[j] == dist[u] + w[i])
{
cnt[j] += cnt[u];
if(num[j] < num[u] + 1)
{
num[j] = num[u] + 1;
sum[j] = sum[u] + a[j];
pre[j] = u;
}
else if(num[j] == num[u] + 1)
{
if(sum[j] < sum[u] + a[j])
{
num[j] = num[u] + 1;
sum[j] = sum[u] + a[j];
pre[j] = u;
}
}
}
}
}
}
void solve()
{
memset(h,-1,sizeof(h));
memset(pre,-1,sizeof(pre));
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
cin>>st>>ed;
mp[st] = ++tot,mp[ed] = ++tot;
mp2[1] = st,mp2[2] = ed;
for(int i=0;i<n-1;++i)
{
string s; cin>>s; int x; cin>>x;
if(mp[s]) ;
else
{
mp[s] = ++tot;
mp2[tot] = s;
}
a[mp[s]] = x;
}
while(m--)
{
string a,b; int z;
cin>>a>>b>>z;
int x = mp[a];
int y = mp[b];
add(x,y,z);
add(y,x,z);
}
Dij(mp[st]);
vector<string> va;
int now = mp[ed];
while(now != -1)
{
va.push_back(mp2[now]);
now = pre[now];
}
reverse(va.begin(),va.end());
for(int i=0;i<va.size();++i)
{
if(i) cout<<"->";
cout<<va[i];
}
cout<<"\n";
cout<<cnt[mp[ed]]<<" "<<dist[mp[ed]]<<' '<<sum[mp[ed]];
}
signed main(void)
{
solve();
return 0;
}