HDU 3499 Flight 反向建图

来源:互联网 发布:福利ios直播软件 编辑:程序博客网 时间:2024/06/06 17:57

转载请注明本文地址


这道题是磊磊师傅教我的第一道反向建图的题目……顺便练习了一下Dijkstra


题意:有n个地点,m条有向边,给每条边的花费。允许将任意一条边的花费变为一半(向下取整),求起点a到终点b的最小花费。


思路:

1.先正向建图,以a为源点跑Dijkstra

2.再反向建图,以b为源点跑Dijkstra

3.枚举边(作为花费变为一半的边),从a到这条边的起点u使用正向建图的结果,从这条边的终点v使用反向建图的结果,然后再加上这条边边权的一半,就得到这条边花费变为一半时候的总花费。

4.将枚举结果取最小值即为最小花费

5.注意输入是字符串,可以用map


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<map>using namespace std;typedef __int64 ll;const int N=100010;const int M=500010;const ll inf=1LL<<60;struct node{    int to;    ll dis;    node *next;}E[M<<1],*G1[N],*G2[N],*head;int n,m,num;ll d1[N],d2[N];bool inq[N];map<string,int> dict;inline void add(int a,int b,ll c,node *G[]){    head->to=b;    head->dis=c;    head->next=G[a];    G[a]=head++;}inline int change(char *s){    if(dict.count(s)) return dict[s];    else return dict[s]=num++;}void SPFA(int s,ll d[],node *G[]){    deque<int> Q;    Q.push_back(s);    memset(inq,false,sizeof(inq));    fill(d,d+N,inf);    d[s]=0;    int to;    ll dis;    while(!Q.empty())    {        int u=Q.front();        Q.pop_front();        inq[u]=false;        for(node *p=G[u];p;p=p->next)        {            to=p->to;            dis=p->dis;            if(d[to]>d[u]+dis)            {                d[to]=d[u]+dis;                if(!inq[to])                {                    inq[to]=true;                    if(!Q.empty() && d[to]<=d[Q.front()]) Q.push_front(to);                    else Q.push_back(to);                }            }        }    }}int main(){    char s1[20],s2[20];    while(~scanf("%d%d",&n,&m))    {        num=0;        dict.clear();        memset(G1,NULL,sizeof(G1));        memset(G2,NULL,sizeof(G2));        head=E;        int s,t;        ll dis;        for(int i=0;i<m;i++)        {            scanf("%s %s %I64d",s1,s2,&dis);            s=change(s1),t=change(s2);            add(s,t,dis,G1);            add(t,s,dis,G2);        }        scanf("%s %s",s1,s2);        s=dict[s1],t=dict[s2];        SPFA(s,d1,G1);        SPFA(t,d2,G2);        ll ans=inf;        for(int i=0;i<n;i++)        {            for(node *p=G1[i];p;p=p->next)            {                int j=p->to;                if(d1[i]<inf && d2[j]<inf) ans=min(ans,d1[i]+d2[j]+(p->dis)/2);            }        }        if(ans==inf) printf("-1\n");        else printf("%I64d\n",ans);    }    return 0;}


原创粉丝点击