题意:给了n个地点,然后每个地点的名称,若名称相同则可以认为这两个地点距离为0,下面m个关系代表两个地点的距离,有向的边,q个询问,两个点的距离,想做的密码是nefu
思路:简单的最短路题目,因为有相同的点,可以用并查集将这些点放到一个集合中,然后建图建的就是父节点就行了,找相同关系我用的Trie树,但是map应该也可以直接做,没用过map只能写Trie树了,剩下的就是最短路模版,easy~~~
#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=400010;
int f[maxn],num[maxn];
struct edge{
int to,cost;
edge(){}
edge(int a,int b){to=a;cost=b;}
};
typedef pair<int,int>P;
vector<edge>G[maxn];
int dis[maxn];
void dijkstra(int st){
priority_queue<P,vector<P>,greater<P> >que;
fill(dis,dis+maxn,inf);
dis[st]=0;
que.push(P(0,st));
while(!que.empty()){
P p=que.top();que.pop();
int v=p.second;
if(dis[v]<p.first) continue;
for(unsigned int i=0;i<G[v].size();i++){
edge e=G[v][i];
if(dis[e.to]>dis[v]+e.cost){
dis[e.to]=dis[v]+e.cost;
que.push(P(dis[e.to],e.to));
}
}
}
}
int find1(int x){
if(x==f[x]) return f[x];
int t=f[x];
f[x]=find1(f[x]);
return f[x];
}
void unite(int a,int b){
int aa=find1(a);
int bb=find1(b);
if(aa==bb) return ;
f[aa]=bb;
num[bb]+=num[aa];
}
struct Trie{
Trie *next[96];
int v;
};
Trie *root;
char str1[30],str2[30];
void creatTrie(char *str,int idx){
int len=strlen(str);
Trie *p=root,*q;
for(int i=0;i<len;i++){
int id=str[i]-'0';
if(p->next[id]==NULL){
q=(Trie *)malloc(sizeof(Trie));
q->v=0;
for(int j=0;j<96;j++)
q->next[j]=NULL;
p->next[id]=q;
}
p=p->next[id];
}
p->v=idx;
}
int findtrie(char *str){
int len=strlen(str);
Trie *p=root;
for(int i=0;i<len;i++){
int id=str[i]-'0';
p=p->next[id];
if(p==NULL) return 0;
}
return p->v;
}
int dealtrie(Trie *T){
if(T==NULL) return 0;
for(int i=0;i<96;i++) if(T->next[i]!=NULL) dealtrie(T->next[i]);
free(T);
return 0;
}
int main(){
int T,n,cas=1,m,u,v,cost,q;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<maxn;i++) G[i].clear();
for(int i=0;i<=2*n;i++){
f[i]=i;num[i]=1;
}
int k=1;
root=(Trie *)malloc(sizeof(Trie));
for(int i=0;i<96;i++) root->next[i]=NULL;
for(int i=1;i<=n;i++){
scanf("%s",str1);
int ans1=findtrie(str1);
if(ans1==0) creatTrie(str1,i);
else unite(ans1,i);
}
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&cost);
int tmp;
int aa=find1(u),bb=find1(v);
if(aa==bb) tmp=0;
else tmp=cost;
G[aa].push_back(edge(bb,tmp));
}
scanf("%d",&q);
printf("Case #%d:\n",cas++);
while(q--){
scanf("%d%d",&u,&v);
int aa=find1(u),bb=find1(v);
if(aa==bb) printf("0\n");
else{
dijkstra(aa);
if(dis[bb]==inf) printf("-1\n");
else printf("%d\n",dis[bb]);
}
}
dealtrie(root);
}
return 0;
}