链接: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*n using 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; }