HDU
来源:互联网 发布:吾生也有涯而知也启示 编辑:程序博客网 时间:2024/06/06 12:54
Recently, Shua Shua had a big quarrel with his GF. He is so upset that he decides to take a trip to some other city to avoid meeting her. He will travel only by air and he can go to any city if there exists a flight and it can help him reduce the total cost to the destination. There's a problem here: Shua Shua has a special credit card which can reduce half the price of a ticket ( i.e. 100 becomes 50, 99 becomes 49. The original and reduced price are both integers. ). But he can only use it once. He has no idea which flight he should choose to use the card to make the total cost least. Can you help him?
The first line of each test case contains two integers N and M ( 2 <= N <= 100,000
0 <= M <= 500,000 ), representing the number of cities and flights. Each of the following M lines contains "X Y D" representing a flight from city X to city Y with ticket price D ( 1 <= D <= 100,000 ). Notice that not all of the cities will appear in the list! The last line contains "S E" representing the start and end city. X, Y, S, E are all strings consisting of at most 10 alphanumeric characters.
4 4Harbin Beijing 500Harbin Shanghai 1000Beijing Chengdu 600Shanghai Chengdu 400Harbin Chengdu4 0Harbin Chengdu
800-1
In the first sample, Shua Shua should use the card on the flight from Beijing to Chengdu, making the route Harbin->Beijing->Chengdu have the least total cost 800. In the second sample, there's no way for him to get to Chengdu from Harbin, so -1 is needed.
首先要知道这条如果让一条原本是最短路径(假设总距离为x)上最长的边变成半价,最终求得的解不一定是最优的。
我当时有疑惑的地方:
1.边数太多,采用邻接表存储,不知道怎样去重。
2.当时思路错误想着,存储下来路径,然后就不会了。
3.代码重复量太大
解答:1.不需要去重,有放在那里就好。想一想,这些重边都是有一个相同的起点和终点,假如我们先是拿的短的
来松弛,好现在松弛完了,如果在拿来另一条同起同终的边,但是权值大了,我们再去松弛,你能松弛么,明显
dis[v]<dis[u]+w,所以根本不符合判断条件,自动舍弃。同理我们先拿来同起同终的长边,再拿来短边,我们还是满足松弛条件的,自然会松弛。
3.新学习一种结构体,我们把相应的变量和函数都放在这里面,只要换一个变量名就好了。
原始加长版:
#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<math.h>#include<map>#include<queue>#define INF 1e18using namespace std;typedef long long ll;int n,m;map<string,int> flight;int cnt1,cnt2;int st,ed;ll dis1[100010],dis2[100010];int vis[100010];struct edge//枚举边{ int u,v; int w;}Edge[500010];/*这种结构超级麻烦,一会看一下,别人的代码*/struct edge1{ int v,w; int next;}Edge1[500010];int head1[100010];void add_edge1(int u,int v,int w)//建立正边{ Edge1[cnt1].v=v,Edge1[cnt1].w=w; Edge1[cnt1].next=head1[u]; head1[u]=cnt1++;}struct edge2{ int v,w; int next;}Edge2[500010];int head2[500010];void add_edge2(int u,int v,int w)//建立反向边{ Edge2[cnt2].v=v,Edge2[cnt2].w=w; Edge2[cnt2].next=head2[u]; head2[u]=cnt2++;}void spfa1(int st){ for(int i=1;i<=n;i++) dis1[i]=INF; memset(vis,0,sizeof(vis)); dis1[st]=0;//自己距离自己是0 queue<int> q; q.push(st); vis[st]=1; while(q.size()) { int now=q.front(); q.pop(); vis[now]=0; for(int i=head1[now];i!=-1;i=Edge1[i].next) { int v=Edge1[i].v,w=Edge1[i].w; if(dis1[v]>dis1[now]+w) { dis1[v]=dis1[now]+w; if(!vis[v]) { q.push(v); vis[v]=1; } } } }}void spfa2(int ed){ for(int i=1;i<=n;i++) dis2[i]=INF; memset(vis,0,sizeof(vis)); dis2[ed]=0; queue<int> q; q.push(ed); vis[ed]=1; while(q.size()) { int now=q.front(); q.pop(); vis[now]=0; for(int i=head2[now];i!=-1;i=Edge2[i].next) { int v=Edge2[i].v,w=Edge2[i].w; if(dis2[v]>dis2[now]+w) { dis2[v]=dis2[now]+w; if(!vis[v]) { vis[v]=1; q.push(v); } } } }}int main(){ while(~scanf("%d %d",&n,&m)) { cnt1=cnt2=0;//太冗长了 memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); memset(Edge,0,sizeof(Edge)); memset(Edge1,0,sizeof(Edge1)); memset(Edge2,0,sizeof(Edge2)); for(int i=0;i<=n;i++) flight.clear(); string a,b;int w; int it=1; for(int i=0;i<m;i++) { cin>>a>>b>>w; if(!flight[a])//对地名进行标号 flight[a]=it++; if(!flight[b]) flight[b]=it++; Edge[i].u=flight[a],Edge[i].v=flight[b],Edge[i].w=w;//对边进行记录 add_edge1(flight[a],flight[b],w);//添加边,利于后面的遍历 add_edge2(flight[b],flight[a],w); } cin>>a>>b; if(!flight[a]) flight[a]=it++; if(!flight[b]) flight[b]=it++; st=flight[a],ed=flight[b]; spfa1(st);//正向找到距离,也就是正向建图 spfa2(ed);//反向建图找到距离 ll ans=INF; for(int i=0;i<m;i++) { int one,two,val; one=Edge[i].u,two=Edge[i].v; val=Edge[i].w; if(dis1[one]+dis2[two]+val/2<ans) ans=dis1[one]+dis2[two]+val/2; } if(ans!=INF) printf("%I64d\n",ans); else printf("-1\n"); } return 0;}
精简版
#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<math.h>#include<map>#include<queue>#define INF 1e18using namespace std;typedef long long ll;/*就是建立一个结构体,然后将关于他的函数,都封装在这个结构体里面,这样的话,只需要建立一个结构体,我们就不用来重复大量的代码*/int n,m;struct edge//枚举边{ int u,v; int w;}Edge[500010];map<string,int> flight;int st,ed;struct s//把相关的量都封装在这个结构体里面,包括函数,才发现,她竟然还能装函数,666{ int cnt; ll dis[100010]; int vis[100010]; struct edge { int v,w; int next; }Edge[500010]; int head[100010]; void add_edge(int u,int v,int w)//建立正边 { Edge[cnt].v=v,Edge[cnt].w=w; Edge[cnt].next=head[u]; head[u]=cnt++; } void spfa(int st) { for(int i=1;i<=n;i++) dis[i]=INF; memset(vis,0,sizeof(vis)); dis[st]=0;//自己距离自己是0 queue<int> q; q.push(st); vis[st]=1; while(q.size()) { int now=q.front(); q.pop(); vis[now]=0; for(int i=head[now];i!=-1;i=Edge[i].next) { int v=Edge[i].v,w=Edge[i].w; if(dis[v]>dis[now]+w) { dis[v]=dis[now]+w; if(!vis[v]) { q.push(v); vis[v]=1; } } } } }}s1,s2;int main(){ while(~scanf("%d %d",&n,&m)) { s1.cnt=s2.cnt=0; memset(Edge,0,sizeof(Edge)); memset(s1.Edge,0,sizeof(s1.Edge)),memset(s2.Edge,0,sizeof(s2.Edge)); memset(s1.head,-1,sizeof(s1.head)), memset(s2.head,-1,sizeof(s2.head)); for(int i=0;i<=n;i++) flight.clear(); string a,b;int w; int it=1; for(int i=0;i<m;i++) { cin>>a>>b>>w; if(!flight[a])//对地名进行标号 flight[a]=it++; if(!flight[b]) flight[b]=it++; Edge[i].u=flight[a],Edge[i].v=flight[b],Edge[i].w=w;//对边进行记录 s1.add_edge(flight[a],flight[b],w);//添加边,利于后面的遍历 s2.add_edge(flight[b],flight[a],w); } cin>>a>>b; if(!flight[a]) flight[a]=it++; if(!flight[b]) flight[b]=it++; st=flight[a],ed=flight[b]; s1.spfa(st);//正向找到距离,也就是正向建图 s2.spfa(ed);//反向建图找到距离 ll ans=INF; for(int i=0;i<m;i++) { int one,two,val; one=Edge[i].u,two=Edge[i].v; val=Edge[i].w; if(s1.dis[one]+s2.dis[two]+val/2<ans) ans=s1.dis[one]+s2.dis[two]+val/2; } if(ans!=INF) printf("%I64d\n",ans); else printf("-1\n"); } return 0;}
阅读全文
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- HTTP详解(九):拥抱HTTPS
- 表格计算--第六届蓝桥杯国赛 JAVA B组第五题
- 11gR2 grid安装最后报错[INS-20802] Oracle Cluster Verification Utility failed
- HTTP详解(十):HTTPS运作原理
- HTTP详解(十一):数字证书那些事
- HDU
- Android Studio 打包时 Signature Version 选择 V1 V2 说明
- Centos7修改主机名
- 最痛苦的阅读经历·《尘埃落定》
- Dragon of Loowater UVA
- Android-JS&Native交互的几种可行性方案&H5白屏问题解决方式
- Educational Codeforces Round 26 E. Vasya's Function(数论)
- spring配置datasource三种方式
- 抽象类