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;
}
时间: 2024-08-09 22:48:39

HDU 3499 分层图最短路+Trie树的相关文章

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5669 [分析]线段树建树+分层图最短路 #include <cstdio> #include <map> #include <algorithm> #include <vector> #include <iostream> #include <set> #include <queue> #include <string&

poj3635Full Tank?[分层图最短路]

Full Tank? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7248   Accepted: 2338 Description After going through the receipts from your car trip through Europe this summer, you realised that the gas prices varied between the cities you v

BZOJ 2763 分层图最短路

突然发现我不会分层图最短路,写一发. 就是同层中用双向边相连,用单向边连下一层 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <string> 5 #include <cstring> 6 #include <queue> 7 #include <vector> 8 #define pa pair<int,int

【网络流24题】 No.14 孤岛营救问题 (分层图最短路)

[题意] 1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛, 营救被敌军俘虏的大兵瑞恩. 瑞恩被关押在一个迷宫里, 迷宫地形复杂, 但幸好麦克得到了迷宫的地形图. 迷宫的外形是一个长方形, 其南北方向被划分为 N 行,东西方向被划分为 M 列,于是整个迷宫被划分为 N× M 个单元.每一个单元的位置可用一个有序数对(单元的行号,单元的列号)来表示.南北或东西方向相邻的 2 个单元之间可能互通, 也可能有一扇锁着的门,或者是一堵不可逾越的墙.迷宫中有一些单元存放着钥匙, 并

NEFU 1132 分层图最短路

点击打开链接 题意:给出起点和终点,然后有k次机会使得路径上的某些路径的值减半,问从起点到终点的最小花费 思路:很明显的分层图最短路嘛,自己也没有去研究算法的含义,队友和我说就是将图分成了n层,然后将这个可以减半的费用连接这n层,然后跑个类似的最短了就可以了,今天改了一个模版,改成了自己喜欢的风格,明天在做几道分层图在看看概念把,这题就是个模版题 #include <queue> #include <vector> #include <stdio.h> #include

BZOJ_2662_[BeiJing wc2012]冻结_分层图最短路

Description “我要成为魔法少女!”     “那么,以灵魂为代价,你希望得到什么?” “我要将有关魔法和奇迹的一切,封印于卡片之中„„”        在这个愿望被实现以后的世界里,人们享受着魔法卡片(SpellCard,又名符 卡)带来的便捷.   现在,不需要立下契约也可以使用魔法了!你还不来试一试?   比如,我们在魔法百科全书(Encyclopedia  of  Spells)里用“freeze”作为关 键字来查询,会有很多有趣的结果. 例如,我们熟知的Cirno,她的冰冻魔

分层图最短路

分层图最短路,就是在分层图上解决最短路问题一般模型为:在一张图上,有k次机会可以通过一条边而不需要计算权值(免费过路),求从起点到终点的最短路线常规思路:想象将一个点拆分为k + 1个点,分别表示到这个点时,免费权消耗了0次,1次,2次......k次这样实际我们可以把这k个点想象成对应dp的不同的状态dis[i][j]表示到第i个点时,消耗了j次乘车权后的最短路线我们用to表示要到达的点,x表示父亲节点,就有dis[to][j] = min(dis[x][j] + val(x, to), di

P4568 飞行路线 分层图最短路

P4568 飞行路线 分层图最短路 分层图最短路 问题模型 求最短路时,可有\(k\)次更改边权(减为0) 思路 在普通求\(Dijkstra\)基础上,\(dis[x][j]\)多开一维\(j\)以存已用了多少次机会,然后每次松弛时,做完普通松弛操作后,还要使用一次机会(如果可以),类同\(DP\). 每次普通松弛: \[ dis[to][j]=min\{dis[cur][j], dis[to][j]\} \] 如果还可以使用(\(j<k\)): \[ dis[to][j+1] = min\{

[P4568][JLOI2011] 飞行路线 (分层图+最短路)

题意:有n个城市,m条航线,每条航线都有一个权值,并且还多了k次免费航行的机会,求1~n的最短路: 做法:分层图+最短路: 1.分层图:因为多了k次免费航行,所以可以考虑建出k+1个图,然后跑一遍最短路: 2.最短路:既然能写分层图,那么最短路应该都会了吧,可以用 dijkstra 或 SPFA : 附上代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm>