hdu3499(分层图最短路 or 反向建图)

传送门

方法一:分层图

#include<bits/stdc++.h>
#define per(i,a,b) for(int i=a;i<=b;i++)
#define mod 1000000007
using namespace std;
typedef long long ll;
const ll inf =23333333333333333LL;
const double eps=1e-8;
int T;
int read(){
    char ch=getchar();
    int res=0,f=0;
    while(ch<‘0‘ || ch>‘9‘){f=(ch==‘-‘?-1:1);ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){res=res*10+(ch-‘0‘);ch=getchar();}
    return res*f;
}
// ------------------------head
const int siz=100005;
map<string,int> mp;
int mcnt=0,n,m;
int d;
char x[15],y[15],schar[15],echar[15];
int head[siz],Enum=0;
ll dis[siz][2];
bool vis[siz][2];
int st,ed;
struct Edge{int to,w,ne;}edge[siz*5];
void add_edge(int a,int b,int c){
    edge[Enum].to=b;
    edge[Enum].w=c;
    edge[Enum].ne=head[a];
    head[a]=Enum++;
}
void init()
{
    memset(head,-1,sizeof(head));
    Enum=0;
    mp.clear();
    mcnt=0;
}
int _hash(char *s){//char*作为实参传给string形参会自动变
    if(mp.count(s)>0)return mp[s];//string作为形参传给char*要转变s.c_str();
    else return mp[s]=mcnt++;
}
struct Qnode{
    int u;
    ll _dis;
    int layer;//位于分层图的哪层
    Qnode(){}
    Qnode(ll a,int b,int c):_dis(a),u(b),layer(c){}
    bool operator<(const Qnode&rhs)const{return _dis>rhs._dis;}//一定要加const
};
void Dijkstra(){
    priority_queue<Qnode>que;
    while(!que.empty())que.pop();
    memset(vis,false,sizeof(vis));
    per(i,0,n){dis[i][0]=inf;dis[i][1]=inf;}
    que.push(Qnode(0LL,st,0));
    dis[st][0]=0; //注意初始化的是st点,而不是0点,这里没注意到!!!
    vis[st][0]=true;
    Qnode tmp;
    while(!que.empty()){
        tmp=que.top();que.pop();
        int u=tmp.u,layer=tmp.layer;
        ll _dis=tmp._dis;
        //printf("dis:%lld   u:%d   layer:%d\n",_dis,u,layer);//
        vis[u][layer]=true;
        //if(u==ed && layer==1)return;//
        //printf("dis[%d]:%lld\n",u,dis[u][0]);//
        for(int i=head[u];i!=-1;i=edge[i].ne){
            int v=edge[i].to,w=edge[i].w;
            //printf("w:%d\n",w);exit(0);//
            //printf("v:%d  \n");//
            //printf("dis[u][layer]:%lld\n",dis[u][layer]);//
            //printf("dis[v][layer+1]:%lld  dis[v][layer]:%lld  w:%d\n",dis[v][layer+1],dis[v][layer],w);//
            //if(dis[v][layer+1]>dis[u][layer]+w/2)printf("cas1 ok\n");else printf("cas1 no\n");//
            if(layer<1 && !vis[v][layer+1] &&dis[v][layer+1]>dis[u][layer]+w/2){
                dis[v][layer+1]=dis[u][layer]+w/2;
                //printf("Push  v%d  dis:%lld  layer:%d\n",v,dis[v][layer],layer+1);//
                que.push(Qnode(dis[v][layer+1],v,layer+1));
            }
            if(!vis[v][layer] && dis[v][layer]>dis[u][layer]+w){
                dis[v][layer]=dis[u][layer]+w;
                que.push(Qnode(dis[v][layer],v,layer));
            }
        }
    }
}

int main()
{
    while(scanf("%d %d",&n,&m)!=EOF){
        init();
        per(i,1,m){
            scanf("%s %s %d",x,y,&d);
            int xn=_hash(x),yn=_hash(y);
            //printf("%s:%d %s:%d d:%d\n",x,xn,y,yn,d);//
            add_edge(xn,yn,d);
        }
        scanf("%s %s",schar,echar);
        if(mp.count(schar)==0||mp.count(echar)==0){printf("-1\n");continue;}
        st=_hash(schar);ed=_hash(echar);
        //printf("%s:%d  %s:%d\n",schar,st,echar,ed);//
        Dijkstra();
        ll ans=min(dis[ed][0],dis[ed][1]);
        if(ans==inf)printf("-1\n");
        else printf("%lld\n",ans);
    }

    return 0;
}

方法二:反向建图

原文地址:https://www.cnblogs.com/WindFreedom/p/9597556.html

时间: 2024-10-08 11:31:11

hdu3499(分层图最短路 or 反向建图)的相关文章

hdu 1535 Invitation Cards(有向图的来回最短路,要反向建图)

题目: 链接:点击打开链接 题意: 给一个图,求1到各点和各点到1最短路. 思路: 先spfa,然后反向建图,在spfa就行了. 代码: #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; #define INF 100000000 const int N = 1000010; struct node{ int u,v,w

poj1122 FDNY to the Rescue!(dij+反向建图+输出路径)

题目链接:poj1122 FDNY to the Rescue! 题意:给出矩阵,矩阵中每个元素tij表示从第i个交叉路口到第j个交叉路口所需时间,若tij为-1则表示两交叉路口之间没有直接路径,再给出火警位置所在的交叉路口 和 一个或多个消防站所处的交叉路口位置.输出要求按消防站到火警位置所需时间从小到大排列,输出信息包括消防站位置(初始位置),火警位置(目标位置),所需时间,最短路径上每个交叉路口. 题解:反向建图,从火警位置求一次最短路,求最短路时记录路径,按时间从小到大输出. 1 #in

VJ - H - Almost the shortest route - 图论(反向建图)

https://vjudge.net/contest/351913#problem/H N cities (2 ≤ N ≤ 10 000 ) are connected by a network of M one-way roads (1 ≤ M < 100 000 000 ). It is known that these roads do not cross outside the cities. The numeration of the cities and the roads star

HDU2647(拓扑排序+反向建图)

题意不说了,说下思路. 给出的关系是a要求的工资要比b的工资多,由于尽可能的让老板少付钱,那么a的工资就是b的工资+1,可以确定关系为a>b,根据拓扑排序建边的原则是把"小于"关系看成有向边,那么我们可以建边v->u. #include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <algorithm> #

HDU1535Invitation Cards(有向图,正向建图和反向建图各spfa一次)

Invitation Cards Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2374    Accepted Submission(s): 1151 Problem Description In the age of television, not many people attend theater performances.

POJ 3687 反向建图+拓扑

Labeling Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11146   Accepted: 3192 Description Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that: No two balls share

HDU4857——逃生(反向建图+拓扑排序)

逃生 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社会是不平等的,这些人有的穷有的富.1号最富,2号第二富,以此类推.有钱人就贿赂负责人,所以他们有一些好处.负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推.那么你就要安排大家的顺序.我们保证一

HDU 3639 Hawk-and-Chicken(强连通缩点+反向建图)

http://acm.hdu.edu.cn/showproblem.php?pid=3639 题意: 有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两票),输出最多能获得的票数是多少张和获得最多票数的人是谁? 思路: 先强连通缩点反向建图,在计算强连通的时候,需要保存每个连通分支的结点个数. 为什么要反向建图呢?因为要寻找票数最多的,那么肯定是入度为0的点,然后dfs计算它的子节点的

[CF825E] Minimal Labels(反向建图,拓扑排序)

题目链接:http://codeforces.com/problemset/problem/825/E 题意:给一个有向图,求一个排列,这个排列是每一个点的序号,使得序号对应的点的排序符合拓扑序并且这个排列字典序最小. 直接跑字典序最小的拓扑排序是不行的,因为那样只是确保点的字典序而非这个排列的字典序,比如这个数据: 10 15 2 反过来考虑,点号大的入度为0的点一定排在后面,这个位置确定了.但是点好小的入度为0的未必一定排在前面,因为这个点之前可能有入度不为0,但是与此点无关的点在前面,按题