题目链接
思路:1.使用哈希表将字符串转化为图的头结点的下标,并且在图的头结点中另外存储作为此点到起点的最短距离min_dis、最大杀敌数max_enemies、最长路径长max_len以及从起点出发到达此点的最多路径cnt的下标.
2.使用dijkstra算法求取最短路.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAX = 2e2 + 3;
const int INF = 0x7ffffff;
const int MIN = 0;
int cnt[MAX];
int num;
struct point {//邻接点
char to[4];
int dis;
point(char* a, int b) { strcpy(to, a); dis = b; }
point() {};
};
struct head {//头结点
char from[4];
int enemy;
int pos;
vector<point*>adjcent;
head(char* a, int b, int c) { strcpy(from, a); enemy = b; pos = c; }
head() {};
};
int Size, N;
int k;//头结点中存储下标
char pre[MAX][4];//前接点
int max_enemies[MAX];
int min_dis[MAX];
int max_len[MAX];
bool done[MAX];
point* Heap[MAX];//在堆排序时移动指针
vector<head*>e[MAX];//图
int find(int x);//寻找大于容量的第一个素数
int Hash_Table(char* tmp);//哈希
void Insert(point* tmp);//最小堆的插入
point* Delete();//从最小堆中删除并取得堆顶最小元素
void dijkstra(char* s, char* e);
bool cmp(point* A, point* B);
void init(char* s);
void print_path(char* end);//打印路径
head* find_pos(int hash, char* name);//根据哈希值找到头结点
int main() {
int M;
char tmp[4], tmp1[4];
int enemy, dis;
num = find(N);
scanf("%d%d", &N, &M);
char start[4], end[4];
scanf("%s%s", start, end);
int has = Hash_Table(start);
head* H1 = new head(start, 0, k++);
e[has].push_back(H1);
for (int i = 0; i < N - 1; i++) {
scanf("\n%s%d", tmp, &enemy);
int hash = Hash_Table(tmp);
head* H = new head(tmp, enemy, k++);
e[hash].push_back(H);
}
for (int i = 0; i < M; i++) {
scanf("\n%s%s%d", tmp, tmp1, &dis);
head* H1 = find_pos(Hash_Table(tmp), tmp);
head* H2 = find_pos(Hash_Table(tmp1), tmp1);
point* t1 = new point(tmp1, dis);
point* t2 = new point(tmp, dis);
H1->adjcent.push_back(t1);
H2->adjcent.push_back(t2);
}
dijkstra(start, end);
print_path(end);
int end_pos = find_pos(Hash_Table(end), end)->pos;
printf("\n%d %d %d", cnt[end_pos], min_dis[end_pos], max_enemies[end_pos]);
}
int find(int x) {
int i, j;
for (i = x + 1;; i++) {
for (j = 2; j <= sqrt(i); j++) {
if (i % j == 0)
break;
}
if (j == (int)sqrt(i) + 1)
return i;
}
}
int Hash_Table(char* tmp) {
unsigned int seed = 31, sum = 0;
while (*tmp) {
sum = sum * 31 + (*tmp) - 'A';
tmp++;
}
return (sum & 0x7fffffff) % num;
}
void Insert(point* tmp) {
Size++;
int i;
for (i = Size; i != 1 && cmp(tmp, Heap[i / 2]); i /= 2)
Heap[i] = Heap[i / 2];
Heap[i] = tmp;
}
point* Delete() {
point* Max = Heap[1];
point* tmp = Heap[Size--];
int parent, child;
for (parent = 1; parent * 2 <= Size; parent = child) {
child = parent * 2;
if (child != Size && cmp(Heap[child + 1], Heap[child]))
child++;
if (cmp(Heap[child], tmp))
Heap[parent] = Heap[child];
else
break;
}
Heap[parent] = tmp;
return Max;
}
void dijkstra(char* s, char* e) {
init(s);
point* Head = new point{ s,0 };
Insert(Head);
while (Size) {
point* tmp = Delete();
head* T = find_pos(Hash_Table(tmp->to), tmp->to);
if (done[T->pos])
continue;
done[T->pos] = true;
int t = T->adjcent.size();
for (int i = 0; i < t; i++) {
point* Tmp = T->adjcent[i];
head* V = find_pos(Hash_Table(Tmp->to), Tmp->to);
if (done[V->pos])
continue;
if (min_dis[V->pos] > min_dis[T->pos] + Tmp->dis) {
strcpy(pre[V->pos], T->from);
cnt[V->pos] = cnt[T->pos];
min_dis[V->pos] = min_dis[T->pos] + Tmp->dis;
max_enemies[V->pos] = max_enemies[T->pos] + V->enemy;
max_len[V->pos] = max_len[T->pos] + 1;
point* TMP = new point(Tmp->to, min_dis[V->pos]);
Insert(TMP);
}
else if (min_dis[V->pos] == min_dis[T->pos] + Tmp->dis) {
cnt[V->pos] += cnt[T->pos];
if (max_len[V->pos] < max_len[T->pos] + 1) {
max_len[V->pos] = max_len[T->pos] + 1;
max_enemies[V->pos] = max_enemies[T->pos] + V->enemy;
strcpy(pre[V->pos], T->from);
}
else if (max_len[V->pos] == max_len[T->pos] + 1) {
if (max_enemies[V->pos] < max_enemies[T->pos] + V->enemy) {
max_enemies[V->pos] = max_enemies[T->pos] + V->enemy;
strcpy(pre[V->pos], T->from);
}
}
}
}
}
}
bool cmp(point* A, point* B) {
return A->dis < B->dis;
}
void init(char* s) {
head* H = find_pos(Hash_Table(s), s);
for (int i = 0; i <= N; i++) {
min_dis[i] = INF;
max_len[i] = 0;
max_enemies[i] = 0;
done[i] = 0;
cnt[i] = 0;
}
min_dis[H->pos] = 0;
cnt[H->pos] = 1;
strcpy(pre[H->pos], s);
}
head* find_pos(int hash, char* name) {
int t = e[hash].size();
for (int i = 0; i < t; i++)
if (!strcmp(name, e[hash][i]->from))
return e[hash][i];
}
void print_path(char* end) {
head* H = find_pos(Hash_Table(end), end);
if (!strcmp(pre[H->pos], end))
printf("%s", end);
else {
print_path(pre[H->pos]);
printf("->%s", end);
}
}