bzoj2763【JLOI2011】飞行路线

来源:互联网 发布:淘宝卖家必备工具2016 编辑:程序博客网 时间:2024/04/29 20:13

2763: [JLOI2011]飞行路线

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1367  Solved: 527
[Submit][Status][Discuss]

Description

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

Input

数据的第一行有三个整数,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

 
只有一行,包含一个整数,为最少花费。

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

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.


Source




用dis[i][j]表示从起点到s点免费j次的最少花费,每次使用SPFA更新免费相同次数的最少花费,同时更新多使用一次免费得最少花费。

我最初的做法是对于每一条边(u,v,w)都添加2*k条边,这样会超出时间限制。后来发现没有必要添加2*k条边,只需添加2条边即可。




#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)#define LL long long#define MAXM 100005#define MAXN 10005#define INF 1000000000using namespace std;struct edge_type{int next,to,w;}e[MAXM];int n,m,k,s,t,a,b,c,ans,cnt=0,head[MAXN],dis[MAXN][11];bool inq[MAXN][11];queue<int>q1,q2;void add_edge(int u,int v,int w){e[++cnt].to=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;}void spfa(){memset(dis,0x7f,sizeof(dis));dis[s][0]=0;memset(inq,false,sizeof(inq));q1.push(s);q2.push(0);inq[s][0]=true;while (!q1.empty()){int x=q1.front();int tmp=q2.front();q1.pop();q2.pop();inq[x][tmp]=false;for(int p=head[x];p;p=e[p].next){int y=e[p].to;if (dis[y][tmp]>dis[x][tmp]+e[p].w){dis[y][tmp]=dis[x][tmp]+e[p].w;if (!inq[y][tmp]){q1.push(y);q2.push(tmp);inq[y][tmp]=true;}}if (tmp<k&&dis[y][tmp+1]>dis[x][tmp]){dis[y][tmp+1]=dis[x][tmp];if (!inq[y][tmp+1]){q1.push(y);q2.push(tmp+1);inq[y][tmp+1]=true;}}}}}int main(){//freopen("input.in","r",stdin);memset(head,0,sizeof(head));ans=INF;scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);F(i,1,m){scanf("%d%d%d",&a,&b,&c);add_edge(a,b,c);add_edge(b,a,c);}spfa();F(i,0,k) ans=min(ans,dis[t][i]);printf("%d\n",ans);}


0 0
原创粉丝点击