【spfa变形】:出行

来源:互联网 发布:xbox游戏知乎 编辑:程序博客网 时间:2024/04/27 04:39

【题目描述】

某人打算外出旅游,他从起点城市1出发,计划到达城市n。城市之间被一些航线连通, 航线可以从任意方向飞行。由于是航空公司会员,他获得一次半价(半价以后价格只保留整数部分)机票的折扣券,使用的时机可以任意安排。

【输入】

输入第一行包含两个数n, m,表示城市数量和航线数量。

接下来的m行每行有3个数ai, bi, wi,分别表示第i条航线连接的第一个城市和第二个城市,以及航线的费用。

【输出】

输出一个整数,表示路途中花费的最小值。

【输出样例】

3 3

1 2 3

2 3 4

3 1 8

 

【输出样例】

4

 

【样例解释】

直接从 1号城市飞到3号城市并出示折扣券是最优方案

 

【数据规模】

对于30%的数据,n<=100,m<=100

对于50%的数据,n<=1000,m<=1500

对于所有数据,2<=n<=10000,1<=m<=100000, 1<=ai, bi<=n, wi<=10000,1<=n<=m。

保证存在一条路径可以从城市1到城市n的飞行方案。

      因为题目中要求可在某条路上半价,所以在spfa中要进行部分改动。

#include<cstdio>//spfa#include<algorithm>#include<cstring>using namespace std;const int maxn=10005;const int maxe=200005;const int INF=0x7f7f7f;struct edge{int to,next;int value;}e[maxe];int n,m;int a,b,w;int k=0;long long dist[maxn];long long dist2[maxn];int queue[maxe];bool visit[maxn];int tail,qhead;int head[maxe];int num[maxe];void add(int u,int v,int w){k++;e[k].to=v;e[k].value=w;e[k].next=head[u];head[u]=k;}void spfa(int s,int t){memset(visit,false,sizeof(visit));memset(dist,INF,sizeof(dist));memset(dist2,INF,sizeof(dist2));qhead=0;tail=1;queue[tail]=s;dist[s]=0;dist2[s]=0;visit[s]=true;while(qhead<tail){qhead++;int p=queue[qhead];visit[p]=false;int p1=head[p];while(p1!=0){bool flag=1;//记录有没有被松弛过 if(dist[e[p1].to]>dist[p]+e[p1].value){dist[e[p1].to]=dist[p]+e[p1].value;flag=0;}if(dist2[e[p1].to]>dist2[p]+e[p1].value){dist2[e[p1].to]=dist2[p]+e[p1].value;flag=0;}if(dist2[e[p1].to]>dist[p]+e[p1].value/2){dist2[e[p1].to]=dist[p]+e[p1].value/2;flag=0;}if(!flag&&!visit[e[p1].to]){tail++;queue[tail]=e[p1].to;visit[e[p1].to]=true;}    p1=e[p1].next;}}printf("%lld",dist2[t]);}int main(){freopen("trip.in","r",stdin);    freopen("trip.out","w",stdout);scanf("%d %d",&n,&m);for(int i=1;i<=m;i++){scanf("%d %d %d",&a,&b,&w);add(a,b,w);add(b,a,w);}spfa(1,n);return 0;}/*5 61 4 11 2 112 3 13 4 21 5 162 5 4*/


0 0
原创粉丝点击