hdu 3499 Flight (最短路径)
Flight
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2014 Accepted Submission(s): 428
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.
Harbin Beijing 500
Harbin Shanghai 1000
Beijing Chengdu 600
Shanghai Chengdu 400
Harbin Chengdu
4 0
Harbin Chengdu
-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.
题意:
在N个点,M条带权边的图上,查询从点s到点e的最短路径,不过,可以有一次机会可以把一条边的权值变成原来的一半。
小菜代码(双向求解,G++不能过...):
//6890MS 41488K 2295 B C++
/*
建图双向求解
*/
#include<iostream>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define N 100005
using namespace std;
struct node{
__int64 v,w;
node(__int64 a,__int64 b){
v=a;w=b;
}
};
const __int64 inf=(_I64_MAX)/;
__int64 dis[][N];
bool vis[N];
__int64 from[*N],to[*N],weight[*N]; //记录边信息
vector<node>V[][N];
map<string,__int64>M;
__int64 n,m,sign;
__int64 start,end;
void spfa()
{
__int64 s;
if(sign==) s=start;
else s=end;
for(int i=;i<=n;i++)
dis[sign][i]=inf;
memset(vis,false,sizeof(vis));
queue<int>Q;
Q.push(s);
dis[sign][s]=;
while(!Q.empty()){
int u=Q.front();
Q.pop();
vis[u]=false;
int n0=V[sign][u].size();
for(int i=;i<n0;i++){
__int64 v=V[sign][u][i].v;
__int64 w=V[sign][u][i].w;
if(dis[sign][v]>dis[sign][u]+w){
dis[sign][v]=dis[sign][u]+w;
if(!vis[v]){
Q.push(v);
vis[v]=true;
}
}
}
}
}
int main(void)
{
string a,b;
__int64 c;
while(cin>>n>>m)
{
M.clear();
for(int i=;i<=n;i++){
V[][i].clear();
V[][i].clear();
}
int id=;
for(int i=;i<m;i++){
cin>>a>>b>>c;
if(M[a]==) M[a]=++id;
if(M[b]==) M[b]=++id;
V[][M[a]].push_back(node(M[b],c));
V[][M[b]].push_back(node(M[a],c));
from[i]=M[a];
to[i]=M[b];
weight[i]=c;
}
cin>>a>>b;
if(M[a]== || M[b]==){
puts("-1");continue;
}
start=M[a];
end=M[b]; if(start==end){
puts("");continue;
} sign=;
spfa();
if(dis[sign][end]==inf){
puts("-1");continue;
} sign=;
spfa(); __int64 ans=inf;
for(int i=;i<m;i++){
ans=min(ans,dis[][from[i]]+dis[][to[i]]+weight[i]/);
}
if(ans==inf) puts("-1");
else printf("%I64d\n",ans);
}
return ;
}
分层图思想:
//6078MS 23744K 1906 B C++
/* 转自:http://yomean.blog.163.com/blog/static/189420225201110282390985/ 一看就想到了分层图,不过如果用分层图,有点杀鸡用牛刀的感觉,因为只有两层。但我还是写了,最后AC了。不过网上很多人都是用建反两向边求解。
而对于分层图求最短路径问题,我们要注意的是,层与层之间的连线都是单向的,而且是从下一层指向上一层,而我们求最短路径的时候,起点总是在下一层,而终点总是在上一层,所以我们可以将经过层与层之间的特殊边的数目控制在n - 1(n是层数)。 */
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#define N 100005
#define inf (_I64_MAX)/2
using namespace std;
int n,m;
int head[*N],vis[*N];
int now,index,k;
__int64 dis[*N];
char name[N][];
map<string,int>M;
struct node{
int v,w,next;
}edge[*N];
void addedge(int u,int v,int w)
{
edge[index].v=v;
edge[index].w=w;
edge[index].next=head[u];
head[u]=index++;
}
struct cmp{
bool operator()(int a,int b){
return dis[a]>dis[b];
}
};
priority_queue<int,vector<int>,cmp>Q;
void init()
{
while(!Q.empty()) Q.pop();
M.erase(M.begin(),M.end());
for(int i=;i<*n;i++){
vis[i]=false;
head[i]=-;
}
now=;
index=;
}
void dij(int s,int e)
{
for(int i=;i<=*n;i++){
dis[i]=inf;vis[i]=false;
}
dis[s]=;
vis[s]=true;
Q.push(s);
while(!Q.empty()){
int u=Q.top();
Q.pop();
if(u==e){
printf("%I64d\n",dis[u]);
return;
}
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(!vis[v] && dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
Q.push(v);
}
}
}
}
int main(void)
{
string a,b;
int x,y,c;
while(cin>>n>>m)
{
init();
for(int i=;i<m;i++){
cin>>a>>b>>c;
if(M.find(a)==M.end()) M[a]=now++;
if(M.find(b)==M.end()) M[b]=now++;
addedge(M[a],M[b],c);
addedge(M[a]+n,M[b]+n,c);
addedge(M[a]+n,M[b],c/);
}
cin>>a>>b;
__int64 ans=inf;
if(M.find(a)==M.end() || M.find(b)==M.end()){
puts("-1");continue;
}
else dij(M[a]+n,M[b]);
}
return ;
}
找了一个G++能过的,不过没自己实现,略感无语
//3765MS 28756K 2269 B G++
//转载: http://blog.csdn.net/shoutmon/article/details/8583984
/* 思路: 1.先正向建图,以a为源点跑Dijkstra 2.再反向建图,以b为源点跑Dijkstra 3.枚举边(作为花费变为一半的边),从a到这条边的起点u使用正向建图的结果,从这条边的终点v使用反向建图的结果,然后再加上这条边边权的一半,就得到这条边花费变为一半时候的总花费。 4.将枚举结果取最小值即为最小花费 5.注意输入是字符串,可以用map */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<map> using namespace std; typedef __int64 ll; const int N=;
const int M=;
const ll inf=1LL<<; struct node
{
int to;
ll dis;
node *next;
}E[M<<],*G1[N],*G2[N],*head; int n,m,num;
ll d1[N],d2[N];
bool inq[N];
map<string,int> dict; inline void add(int a,int b,ll c,node *G[])
{
head->to=b;
head->dis=c;
head->next=G[a];
G[a]=head++;
} inline int change(char *s)
{
if(dict.count(s)) return dict[s];
else return dict[s]=num++;
} void SPFA(int s,ll d[],node *G[])
{ deque<int> Q;
Q.push_back(s);
memset(inq,false,sizeof(inq));
fill(d,d+N,inf);
d[s]=;
int to;
ll dis;
while(!Q.empty())
{
int u=Q.front();
Q.pop_front();
inq[u]=false;
for(node *p=G[u];p;p=p->next)
{
to=p->to;
dis=p->dis;
if(d[to]>d[u]+dis)
{
d[to]=d[u]+dis;
if(!Q.empty())
{
if(d[to]>d[Q.front()]) Q.push_back(to);
else Q.push_front(to);
}
else Q.push_back(to);
}
}
}
} int main()
{
char s1[],s2[];
while(~scanf("%d%d",&n,&m))
{
num=;
dict.clear();
memset(G1,NULL,sizeof(G1));
memset(G2,NULL,sizeof(G2));
head=E;
int s,t;
ll dis;
for(int i=;i<m;i++)
{
scanf("%s %s %I64d",s1,s2,&dis);
s=change(s1),t=change(s2);
add(s,t,dis,G1);
add(t,s,dis,G2);
}
scanf("%s %s",s1,s2);
s=dict[s1],t=dict[s2]; SPFA(s,d1,G1);
SPFA(t,d2,G2); ll ans=inf;
for(int i=;i<n;i++)
{
for(node *p=G1[i];p;p=p->next)
{
int j=p->to;
if(d1[i]<inf && d2[j]<inf) ans=min(ans,d1[i]+d2[j]+(p->dis)/);
}
} if(ans==inf) printf("-1\n");
else printf("%I64d\n",ans);
}
return ;
}
hdu 3499 Flight (最短路径)的更多相关文章
- HDU 3499 Flight spfa+dp
Flight Time Limit : 20000/10000ms (Java/Other) Memory Limit : 65535/65535K (Java/Other) Total Subm ...
- HDU - 3499 Flight 双向SPFA+枚举中间边
Flight Recently, Shua Shua had a big quarrel with his GF. He is so upset that he decides to take a t ...
- hdu 3499 flight 【分层图】+【Dijkstra】
<题目链接> 题目大意: 现在给你一些点,这些点之间存在一些有向边,每条边都有对应的边权,有一次机会能够使某条边的边权变为原来的1/2,求从起点到终点的最短距离. 解题分析: 分层图最短路 ...
- Flight HDU - 3499 (分层最短路)
Recently, Shua Shua had a big quarrel with his GF. He is so upset that he decides to take a trip to ...
- HDU ACM 3790 最短路径问题
最短路径问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- hdu 3790 (最短路径问题dijkstra)
主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起 ...
- HDU 2112 HDU Today(最短路径+map)
HDU Today Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- hdu 1688 Sightseeing (最短路径)
Sightseeing Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu DIY FLIGHT GAME (dfs)
FLIGHT GAME Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other) Total S ...
随机推荐
- 获取Grid后台动态添加的子项
例:Grid的子项是包含边框的复选框CheckBox //遍历Grid中的子项 foreach (var c in this.grid_box.Children) { Border bd = c as ...
- lnmp安装后,phpmyadmin空白
使用lnmp 一键安装后,运行phpinfo是没有问题的,说明php没有问题,但是运行phpmyadmin确实一片空白,网上说的解决方案有几种: 1.config.inc.php增加一个配置$cfg[ ...
- 微信小程序开发入门学习(1):石头剪刀布小游戏
从今天起开始捣鼓小程序了2018-12-17 10:02:15 跟着教程做了第一个入门实例有兴趣的朋友可以看看: 猜拳游戏布局 程序达到的效果 猜拳游戏的布局是纵向显示了三个组件:文本组件(tex ...
- libvirt笔记(未完待续)
参考源地址:http://libvirt.org/formatdomain.html http://blog.csdn.net/qq250941970/article/details/6022094 ...
- 关于对GitHub的使用
什么是GitHub? GitHub是版本控制和协作的代码托管平台.它可以让你在其他人在任何地方一起工作. 本文主要向您介绍GitHub essentials,如存储库,分支,提交和合并请求.将您创建自 ...
- linux epoll用法
epoll 是 linux 特有的 I/O 复用函数.它是把用户关心的文件描述符事件放在内核的一个事件列表中,故而,无须像select和poll一样每次调用都重复传入文件描述符或事件集.但是, epo ...
- linux-shell——03
mkdir 创建一个新目录格式: mkdir [选项-p][路径]目录名 -p 递归创建多级目录 mkdir -p b/c/e/f/g rmdir 删除一个空目录 touch 创建一个空文件,更新文件 ...
- 我今天的收获,必备stadio 插件
1.ADBWIFI 必须的,说不定你就用到了. 2.ADB Idea 必须 3.JavaDoc 4.Translation 5.Gradle Killer
- Kafka写入流程和副本策略
Kafka写入流程: 1.producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader 2. prod ...
- 腾讯装扮下拉选项卡特效(QQ空间)
<DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" ...