[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
|
样例输出 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 }