BestCoder Round #80 E Road (hdu5669) 【线段树+分层图最短路】

来源:互联网 发布:fedora yum 源 编辑:程序博客网 时间:2024/06/05 01:59

链接:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=688&pid=1005

题意:中文题

分析:官方题解说的很详细了这里就不转了,关键部分已经注释了

代码:

#include <algorithm>#include <iostream>#include <iostream>#include <cstring>#include <cstdio>#include <string>#include <vector>#include <queue>#include <cmath>#include <stack>#include <set>#include <map>#include <ctime>#define INF 0x7fffffff#define Mn 50010*10#define Mm 2000010#define mod 1000000007#define CLR(a,b) memset((a),(b),sizeof((a)))#define CPY(a,b) memcpy ((a), (b), sizeof((a)))#pragma comment(linker, "/STACK:102400000,102400000")#define ul (u<<1)#define ur ((u<<1)|1)#define cnt 4*nusing namespace std;typedef long long ll;struct edge {    int v,w,next;}e[Mm];struct node {    int v,cost;    node(){}    node(int v,int cost):v(v),cost(cost){}    bool operator <(const node a) const {        return a.cost<cost;    }};int tot,head[Mn];void addedge(int u,int v,int w) {    e[tot].v=v;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot++;}int tr[Mn],tr2[Mn];int n,k;void build(int l,int r,int u) {    if(l==r) {        tr[l]=u;        tr2[l]=cnt+u;//第二棵线段树        addedge(tr2[l],tr[l],0);//回到第一颗线段树上        return ;    }    int mid=(l+r)>>1;    build(l,mid,ul);    build(mid+1,r,ur);    addedge(ul,u,0);//第一棵线段树中  儿子连向父亲 表示 如果父亲有连向第二棵线段树的边 a b    addedge(ur,u,0);//则该点可以通过父亲的边连向第二课线段树c d    addedge(cnt+u,cnt+ul,0);//第二棵线段树中 父亲连向儿子 表示上面节点可以通过该边找到实际的节点 c d    addedge(cnt+u,cnt+ur,0);}int s,t,w,tmp;//tmp为两线段树相连的中间结点void query(int l,int r,int u) {    if(s<=l&&t>=r) {        addedge(u,tmp,0);        return ;    }    int mid=(l+r)>>1;    if(s<=mid) query(l,mid,ul);    if(t>mid) query(mid+1,r,ur);}void query2(int l,int r,int u) {    if(s<=l&&t>=r) {        addedge(tmp,u+cnt,w);        return ;    }    int mid=(l+r)>>1;    if(s<=mid) query2(l,mid,ul);    if(t>mid) query2(mid+1,r,ur);}priority_queue<node> q;int dis[Mn][11],vis[Mn][11];int ans;void dijkstra(int st,int ed) {    st=tr[st];ed=tr2[ed];    while(!q.empty()) q.pop();    q.push(node(st,0));    CLR(dis,0x7f);    CLR(vis,0);    dis[st][0]=0;    while(!q.empty()) {        int v=q.top().v;        int u=(v-1)%tmp+1;//求出节点和所在层数 这里是为了在优先队列里少存一个数        int x=(v-u)/tmp;        q.pop();        if(vis[u][x]) continue;        vis[u][x]=1;        for(int i=head[u];~i;i=e[i].next) {            int v=e[i].v;            int cost=e[i].w;            if(!vis[v][x]&&dis[v][x]>dis[u][x]+cost) {                dis[v][x]=dis[u][x]+cost;                q.push(node(v+x*tmp,dis[v][x]));            }            if(x<k) {                if(!vis[v][x+1]&&dis[v][x+1]>dis[u][x]) {                    dis[v][x+1]=dis[u][x];                    q.push(node(v+(x+1)*tmp,dis[v][x+1]));                }            }        }    }    for(int i=0;i<=k;i++)        ans=min(ans,dis[ed][i]);}void init() {    tot=0;    CLR(head,-1);}int main() {    init();    int m,a,b,c,d;    scanf("%d",&n);    scanf("%d%d%d",&n,&m,&k);    build(1,n,1);    tmp=cnt*2;    for(int i=0;i<m;i++) {        scanf("%d%d%d%d%d",&a,&b,&c,&d,&w);        tmp++;s=a;t=b;        query(1,n,1);        s=c;t=d;        query2(1,n,1);        tmp++;        query(1,n,1);  //边是双向的        s=a;t=b;        query2(1,n,1);    }    ans=INF;    dijkstra(1,n);    if(ans>=INF) printf("CreationAugust is a sb!\n");    else printf("%d\n",ans);    return 0;}


0 0
原创粉丝点击