点击打开链接
题意:给了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; }