[BZOJ2763][JLOI2011]飞行路线

题目描述 Description

Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

输入描述 Input Description
数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t<n)
接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<n,a与b不相等,0<=c<=1000)
输出描述 Output Description
  只有一行,包含一个整数,为最少花费。
样例输入 Sample Input
5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
样例输出 Sample Output
8
数据范围及提示 Data Size & Hint
 对于30%的数据,2<=n<=50,1<=m<=300,k=0;

对于50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;

对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.

 好久没有写博客了,今天多来几发:
本题特殊条件是有k次免费,然后我就想到了状态之间的一些转移,类似f(i,j)表示当前到了第i个点,用了j次免费条边的最小花费,转移比较显然,f(i,j)可以转移到f(a,j+1)和f(a,j)。(其中a是i能到达的一些点)然而转移比较复杂,所以就可以把一个状态f(i,j)看成一个点,转移连成一些边,最后从f(s,0)到f(t,k)求一下最短路就好了。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<queue>
 5 #include<cmath>
 6 #include<cstring>
 7 using namespace std;
 8 typedef long long LL;
 9 typedef pair<int,int> PII;
10 #define mp(a,b) make_pair(a,b) 
11 #define mem(a,b) memset(a,b,sizeof(a))
12 inline int read()
13 {
14     int x=0,f=1;char c=getchar();
15     while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
16     while(isdigit(c)){x=x*10+c-'0';c=getchar();}
17     return x*f;
18 }
19 const int maxn=110010,maxm=2000010,oo=2147483647;
20 struct Edge
21 {
22     int u,v,w,next;
23     Edge() {}
24     Edge(int _1,int _2,int _3,int _4):u(_1),v(_2),w(_3),next(_4) {}
25 }e[maxm<<1];
26 int n,m,k,s,t,a,b,c,first[maxn],ce=-1,dis[maxn]; 
27 bool vis[maxn];
28 int id(int a,int b){return b*n+a;}
29 void addEdge(int a,int b,int c){e[++ce]=Edge(a,b,c,first[a]);first[a]=ce;} 
30 int Dijkstra()
31 {
32     priority_queue <PII,vector<PII>,greater<PII> > Q;
33     for(int i=0;i<(k+1)*n;i++)dis[i]=oo;
34     Q.push(make_pair(0,id(s,0)));dis[id(s,0)]=0;
35     while(Q.size())
36     {
37         int now=Q.top().second;Q.pop();
38         if(vis[now])continue;
39         vis[now]=1;
40         for(int i=first[now];i!=-1;i=e[i].next)
41             if(dis[e[i].v]>dis[now]+e[i].w)
42             {
43                 dis[e[i].v]=dis[now]+e[i].w; 
44                 Q.push(make_pair(dis[e[i].v],e[i].v));
45             }
46     }
47     return dis[id(t,k)];
48 }
49 int main()
50 {
51     mem(first,-1);
52     n=read();m=read();k=read();s=read();t=read();
53     for(int i=0;i<m;i++)
54     {
55         a=read(),b=read(),c=read();
56         for(int j=0;j<=k;j++)
57         {
58             addEdge(id(a,j),id(b,j),c);addEdge(id(b,j),id(a,j),c);
59             if(j<k)addEdge(id(a,j),id(b,j+1),0),addEdge(id(b,j),id(a,j+1),0);
60         }
61     }
62     printf("%d",Dijkstra());
63     return 0;
64 }
View Code

 

posted @ 2017-05-17 10:51  小飞淙的云端  阅读(317)  评论(0编辑  收藏  举报