题意:

  给一幅图,要从s点要到e点,图中有两种无向边分别在两个集合中,第一个集合是可以无限次使用的,第二个集合中的边只能挑1条。问如何使距离最短?输出路径,用了第二个集合中的哪条边,最短距离。

思路:

(1)简单易操作方法:既然第二个集合的边只能有1条,就穷举下这些边,可能的边集进行求最短路,同时记录3个答案。复杂度是O(m*k)。

(2)时间复杂度低:不妨先求从s到每个其他点的距离d1[i],再求e到其他每个点的距离d2[i],接下来穷举第二个集合中的每条边u-v,那么最短距离为d1[u]+dis[u][v]+d2[v],注意边是无向的。麻烦在记录路径而已,还是挺容易操作的。复杂度是O(2m+k)。

下面是第一种方法的代码:

 #include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
int n, m, k;
vector<int> vect[N];
int edge_cnt;
struct node
{
int from, to, dis, tag;
node(){};
node(int from,int to,int dis,int tag):from(from),to(to),dis(dis),tag(tag){};
}edge[N*]; void add_node(int from,int to,int dis,int tag)
{
edge[edge_cnt]=node(from,to,dis,tag);
vect[from].push_back(edge_cnt++);
} int tag[N], dist[N], vis[N], path[N];
int dijkstra(int s,int e)
{
memset(dist,0x7f,sizeof(dist));
memset(tag,,sizeof(tag));
memset(vis,,sizeof(vis));
memset(path,,sizeof(path)); priority_queue<pii,vector<pii>,greater<pii> > que;
que.push(make_pair(, s));
dist[s]=; while(!que.empty())
{
int x=que.top().second;
que.pop();
if(vis[x]) continue;
vis[x]=;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if( e.tag> && dist[e.to]>dist[x]+e.dis )
{
dist[e.to]=dist[x]+e.dis;
path[e.to]=x;
if(e.tag==)
{
tag[e.to]=true; //到这个点用了快线
}
que.push( make_pair(dist[e.to],e.to) );
}
}
}
return dist[e];
} void cal(int s ,int e)
{
vector<int> ans;
int quick=, big=dijkstra(s,e), d=e;//先跑了一遍不用快线的 while( d )
{
ans.push_back(d);
d=path[d];
} for(int i=m*; i<(m+k)*; i+= ) //穷举每条可以用的快线
{
edge[i].tag=;
edge[i+].tag=; int dis=dijkstra(s,e);
if( dis<big )
{
big=dis;
ans.clear();
int ed=e, tmp=;
while( ed )
{
if( tag[ed] ) tmp=path[ed]; //有可能没有用到
ans.push_back(ed);
ed=path[ed];
}
quick=tmp;//如果没有用到,也会及时更新为0
}
edge[i].tag=;
edge[i+].tag=;
} reverse(ans.begin(),ans.end());
printf("%d",ans[]); //千万注意输出格式
for(int i=; i<ans.size(); i++) printf(" %d",ans[i]);
printf("\n"); if(quick) printf("%d\n",quick);
else puts("Ticket Not Used");//别忘了 printf("%d\n",big);
} int main()
{
freopen("input.txt", "r", stdin);
int s=, e, a, b, c, ttt=;
while(~scanf("%d%d%d", &n, &s, &e))
{
if(ttt) printf("\n");ttt++;//格式啊!
edge_cnt=;
memset(edge,,sizeof(edge));
for(int i=; i<=n; i++) vect[i].clear();
scanf("%d",&m);
for(int i=; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
add_node(a,b,c,);
add_node(b,a,c,);
}
scanf("%d",&k);
for(int i=; i<k; i++)
{
scanf("%d%d%d",&a,&b,&c);
add_node(a,b,c,);
add_node(b,a,c,);
}
cal(s,e);
}
return ;
}

AC代码

UVA 11374 Airport Express 机场快线(单源最短路,dijkstra,变形)的更多相关文章

  1. UVA - 11374 - Airport Express(堆优化Dijkstra)

    Problem    UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...

  2. UVa 11374 - Airport Express ( dijkstra预处理 )

    起点和终点各做一次单源最短路, d1[i], d2[i]分别代表起点到i点的最短路和终点到i点的最短路,枚举商业线车票cost(a, b);  ans = min( d1[a] + cost(a, b ...

  3. UVA 11374 Airport Express (最短路)

    题目只有一条路径会发生改变. 常见的思路,预处理出S和T的两个单源最短路,然后枚举商业线,商业线两端一定是选择到s和t的最短路. 路径输出可以在求最短路的同时保存pa数组得到一棵最短路树,也可以用di ...

  4. 利用分支限界法求解单源最短路(Dijkstra)问题

    分支限界法定义:采用Best fist search算法,并使用剪枝函数的算法称为分支界限法. 分支限界法解释:按Best first的原则,有选择的在其child中进行扩展,从而舍弃不含有最优解的分 ...

  5. 【算法】单源最短路——Dijkstra

    对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...

  6. 牛客编程巅峰赛S1第6场 - 黄金&钻石&王者 C.星球游戏 (单源最短路,Dijkstra)

    题意:有\(n\)个点,\(m\)条双向边,两个方向的权值都是相等的,可以从\(A\)中的某个点出发走到\(B\)中的某个点,求所有路径中的最短距离,如果A和B中没有点联通,则输出\(-1\). 题解 ...

  7. 洛谷 P5837 [USACO19DEC]Milk Pumping G (单源最短路,dijkstra)

    题意:有一\(n\)个点,\(m\)条边的双向图,每条边都有花费和流量,求从\(1\)~\(n\)的路径中,求\(max\frac{min(f)}{\sum c}\). 题解:对于c,一定是单源最短路 ...

  8. UVA 11374 Airport Express SPFA||dijkstra

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  9. UVA - 11374 Airport Express (Dijkstra模板+枚举)

    Description Problem D: Airport Express In a small city called Iokh, a train service, Airport-Express ...

随机推荐

  1. eclipse中加放js文件报js语法错误解决办法

    1) eclipse设置         window->preference-> JavaScript -> Validator->Errors/Warnings->E ...

  2. Matlab中sort函数的使用

    主要看大神们如何使用,先模仿. [~,y] = sort(v),如果v是向量,那么y返回的是v中的下标(不好表达),看下面的,发现y是是下标,对应的是c中元素*(由小到大排序).使用c(y)就得到了由 ...

  3. PhyreEngine3.8 MSAA resolution

    There is something wrong in PhyreEngine 3.8 to fullfill MSAA, actually, I think it is eqaa You have ...

  4. 字符串匹配--kmp算法原理整理

    kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...

  5. 【锋利的JQuery-学习笔记】广告栏

    效果图: html: <div id="jnImageroll"> <a href="#nogo" id="JS_imgWrap&q ...

  6. Linked List vs Array

    Both Arrays and Linked List can be used to store linear data of similar types, but they both have so ...

  7. POJ2411 Mondriaan's Dream 轮廓线dp

    第一道轮廓线dp,因为不会轮廓线dp我们在南京区域赛的时候没有拿到银,可见知识点的欠缺是我薄弱的环节. 题目就是要你用1*2的多米诺骨排填充一个大小n*m(n,m<=11)的棋盘,问填满它有多少 ...

  8. POJ2996Help Me with the Game

    http://poj.org/problem?id=2996 又是一个大模拟题,表示做模拟题做的恶心,这个题主要是对数据的处理,从表格中将数据取出来再进行处理即可. 主要注意的点就是:1.KQRBN五 ...

  9. hdu 1352 I Conduit!

    计算几何,主要是排序问题,其他都很好做…… ;}

  10. lintcode 中等题: reverse linked list II 翻转链表II

    题目 翻转链表 II 翻转链表中第m个节点到第n个节点的部分 样例 给出链表1->2->3->4->5->null, m = 2 和n = 4,返回1->4-> ...