HDU 3499 分层图最短路+Trie树

Posted Dan__ge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3499 分层图最短路+Trie树相关的知识,希望对你有一定的参考价值。

点击打开链接

题意:给n个城市和m条无向边,然后给了起点和终点,然后你有一次机会使得其中的一张票价减半,问最小花费是多少

思路:明显是裸的分层图嘛,而且层数就只为2比较简单,但是注意的是城市的名字之类的,我用的Trie树来处理的,RE了几次,每组过后将Trie树释放就好了,然后注意那个减半的价钱是直接/2,WA了几次加了1除以的2,o(︶︿︶)o 唉

#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,ll> P;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=200010;
struct edge{
    int to,cost;
    edge(int a,int b){to=a;cost=b;}
};
vector<edge>G[maxn];
int vis[maxn],n,m,k=1;
ll dis[maxn];
ll dijkstra(int s,int t){
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    priority_queue<P, vector<P>, greater<P> >que;
    dis[s]=0;que.push(P(0,s));
    while (!que.empty()){
        P p=que.top();que.pop();
        int v=p.second;
        if (vis[v]) continue;
        vis[v]=1;
        for(int i=0;i<G[v].size();i++){
            edge e=G[v][i];
            if(dis[v]+(ll)e.cost<dis[e.to]){
                dis[e.to]=dis[v]+(ll)e.cost;
                que.push(P(dis[e.to],e.to));
            }
        }
    }
    ll ans=INF;
    for(int i=0;i<=k;i++)
        ans=min(ans,dis[i*n+t]);
    if(ans==INF) return -1;
    return ans;
}
struct Trie{
    Trie *next[63];
    int v;
};
Trie *root;
void creatTrie(char *str,int idx){
    int len=strlen(str);
    Trie *p=root,*q;
    for(int i=0;i<len;i++){
        int id;
        if(str[i]>='0'&&str[i]<='9') id=str[i]-'0';
        else if(str[i]>='A'&&str[i]<='Z') id=str[i]-'A'+10;
        else if(str[i]>='a'&&str[i]<='z') id=str[i]-'a'+36;
        if(p->next[id]==NULL){
            q=(Trie *)malloc(sizeof(Trie));
            q->v=0;
            for(int j=0;j<63;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;
        if(str[i]>='0'&&str[i]<='9') id=str[i]-'0';
        else if(str[i]>='A'&&str[i]<='Z') id=str[i]-'A'+10;
        else if(str[i]>='a'&&str[i]<='z') id=str[i]-'a'+36;
        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<63;i++) if(T->next[i]!=NULL) dealtrie(T->next[i]);
    free(T);
    return 0;
}
int U[maxn*3],V[maxn*3],COST[maxn*3];
char str1[110],str2[110];
int main(){
    while(scanf("%d%d",&n,&m)!=-1){
        for(int i=0;i<maxn;i++) G[i].clear();
        root=(Trie *)malloc(sizeof(Trie));
        for(int i=0;i<63;i++) root->next[i]=NULL;
        int kkk=1;
        for(int i=1;i<=m;i++){
            scanf("%s%s%d",str1,str2,&COST[i]);
            int ans1=findtrie(str1);
            int ans2=findtrie(str2);
            if(ans1==0) creatTrie(str1,kkk++);
            if(ans2==0) creatTrie(str2,kkk++);
            int ss=findtrie(str1);
            int tt=findtrie(str2);
            U[i]=ss;V[i]=tt;
        }
        for(int i=1;i<=m;i++){
            for(int j=0;j<=k;j++){
                G[j*n+U[i]].push_back(edge(j*n+V[i],COST[i]));
                if(j<k) G[j*n+U[i]].push_back(edge((j+1)*n+V[i],COST[i]/2));
            }
        }
        scanf("%s%s",str1,str2);
        int st=findtrie(str1),en=findtrie(str2);
        if(st==0||en==0) printf("-1\n");
        else{
            ll ans=dijkstra(st,en);
            printf("%I64d\n",ans);
        }
        dealtrie(root);
    }
    return 0;
}

以上是关于HDU 3499 分层图最短路+Trie树的主要内容,如果未能解决你的问题,请参考以下文章

最短路 || 分层图最短路

HDU 5669 Road(线段树建树)(分层图最短路)

hdu 3499 flight 分层图+Dijkstra

最短路合集(分层图最短路传递闭包路径还原k短路...)

选择合适的最短路--hdu3499

HDU - 3499 Flight (单源最短路+优惠问题)