热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HDU6181次短路(K短路)

TwoPathsTimeLimit:40002000MS(JavaOthers)MemoryLimit:153428153428K(JavaOthers)Total

Two Paths

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 613    Accepted Submission(s): 312


Problem Description You are given a undirected graph with n nodes (numbered from 1 to n) and m edges. Alice and Bob are now trying to play a game. 
Both of them will take different route from 1 to n (not necessary simple).
Alice always moves first and she is so clever that take one of the shortest path from 1 to n.
Now is the Bob's turn. Help Bob to take possible shortest route from 1 to n.
There's neither multiple edges nor self-loops.
Two paths S and T are considered different if and only if there is an integer i, so that the i-th edge of S is not the same as the i-th edge of T or one of them doesn't exist.
 

 

Input The first line of input contains an integer T(1 <= T <= 15), the number of test cases.
The first line of each test case contains 2 integers n, m (2 <= n, m <= 100000), number of nodes and number of edges. Each of the next m lines contains 3 integers a, b, w (1 <= a, b <= n, 1 <= w <= 1000000000), this means that there's an edge between node a and node b and its length is w.
It is guaranteed that there is at least one path from 1 to n.
Sum of n over all test cases is less than 250000 and sum of m over all test cases is less than 350000.
 

 

Output For each test case print length of valid shortest path in one line.  

 

Sample Input 23 31 2 12 3 41 3 32 11 2 1  

 

Sample Output 53HintFor testcase 1, Alice take path 1 - 3 and its length is 3, and then Bob will take path 1 - 2 - 3 and its length is 5.For testcase 2, Bob will take route 1 - 2 - 1 - 2 and its length is 3 才讲的K短路,第二天多校就考到这个。=-= 比较裸,直接用A*算法+Dij堆优化,不加堆优化的Dij会超时的,而且这个题数据边的w值会很大,所以所有的边的变量,中间累加的变量,数组存下的长度,最后的A*函数返回结果(一开始WA了很多次,就在这里,返回值也要long long,只顾改了变量了,白白WA了几发)都要设置成long long,第二个就是无向边了,建图和反向建图的两个数组都要push两次。这也是一开始反向建图少一个就WA。 
#include 
#include

#include

#include

#include

#include

#define MAXN 100010
#define INF (1LL<<62)
using namespace std;
typedef
long long ll;
typedef pair
<int, ll> P;
int N, M, S, T, K;
ll dist[MAXN];
ll tdist[MAXN];
int cnt[MAXN];
bool f[MAXN];
vector

Adj[MAXN];
vector

Rev[MAXN];
struct Edge {
int to;
ll len;
Edge(){}
Edge(
int t, ll l):to(t), len(l){}
};
priority_queue
q;

bool operator<(const Edge &a, const Edge &b) {
return (a.len + dist[a.to]) > (b.len + dist[b.to]);
}

void dijkstra() {
memset(dist,
0, sizeof(dist));
fill(tdist, tdist
+MAXN, INF);
tdist[T]
= 0;
while(!q.empty()) q.pop();
q.push(Edge(T,
0));
while (!q.empty()) {
int x = q.top().to;
ll d
= q.top().len;
q.pop();
if (tdist[x] continue;
for (int i = 0; i ) {
int y = Rev[x][i].first;
ll len
= Rev[x][i].second;
if (d+ len < tdist[y]) {
tdist[y]
= d + len;
q.push(Edge(y, tdist[y]));
}
}
}
for (int i = 1; i <= N; i++){
dist[i]
= tdist[i];
}
}

//注意这里是long long的返回结果啊!
ll aStar() {
if (dist[S] == INF) return -1;
while (!q.empty()) q.pop();
q.push(Edge(S,
0));
memset(cnt,
0, sizeof(cnt));
while (!q.empty()) {
int x = q.top().to;
ll d
= q.top().len;
q.pop();
cnt[x]
++;
if (cnt[T] == K) return d;
if (cnt[x] > K) continue;
for (int i = 0; i ) {
int y = Adj[x][i].first;
ll len
= Adj[x][i].second;
q.push(Edge(y, d
+len));
}
}

return -1;
}

int main() {
// freopen("in.txt","r",stdin);
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int tt;
cin
>>tt;
while(tt--) {
//初始化,忘了就WA
for(int i = 0; i <= N; i++) {
Adj[i].clear();
Rev[i].clear();
}
int a, b;
ll t;
cin
>> N >> M;
for (int i = 0; i ) {
cin >> a >> b >> t;
Adj[a].push_back(make_pair(b, t));
Adj[b].push_back(make_pair(a, t));
Rev[b].push_back(make_pair(a, t));
Rev[a].push_back(make_pair(b, t));
}
S
= 1;
T
= N;
K
= 2;
// cin >> S >> T >> K;

if (S == T) K++;

dijkstra();
cout
< endl;
}
return 0;
}

 

次短路做法,用的别人模版: 原理就是在存dis最短路的时候同时用另外一个数组存次短路,在最短路交换边和dis[]值得时候,次短路存下新交换的没最短边长的值即可。
#include
#include

#include

#include

#include

#include

using namespace std;
typedef
long long int ll;
#define MAXM 350010
#define MAXN 250010
#define INF 1223372036854775807
typedef pair
int> pp;

typedef
struct node
{
int v;
ll w;
node(
int tv=0,ll tw=0):
v(tv),w(tw){};
}node;

int n,m;
vector
edge[MAXM];
ll dis[MAXN],dis2[MAXN];
//dis[i]表示最短路,dis2[i]表示次短路


void solve()
{
fill(dis
+1,dis+n+1,INF);
fill(dis2
+1,dis2+n+1,INF);


priority_queue
, greater > q; //用优先队列加速搜索
dis[1]=0;
q.push(pp(dis[
1],1)); //second是该边指向(虽然是无向的)的顶点,first是这条边的权值
while(q.size())
{
pp p
=q.top(); q.pop();
int v=p.second;
ll d
=p.first;
if(dis2[v]continue; //如果当前取出的值不是到v的最短路或次短路就contniue,因为v->e的最短边和次短边一定是由->v的最短边和次短边+edge(v,e)得到
for(int i=0;i)
{
int e=edge[v][i].v;
ll d2
=d+edge[v][i].w;
if(dis[e]>d2)
{
swap(dis[e],d2);
q.push(pp(dis[e],e));
}
if(dis2[e]>d2&&d2>dis[v]) //d2>dis[v]防止d2小于dis[v],这样v->e就变成负权边了,但可有可无
{
dis2[e]
=d2;
q.push(pp(dis2[e],e));
}
}
}
printf(
"%lld\n",dis2[n]);


}

int main()
{
int t;
scanf(
"%d",&t);
while(t--)
{
scanf(
"%d%d",&n,&m);
for(int i=1;i<=n;i++) edge[i].clear();
for(int i=0;i)
{
int a,b;
ll c;
scanf(
"%d%d%lld",&a,&b,&c);
edge[a].push_back(node(b,c));
edge[b].push_back(node(a,c));
}
solve();
}
}

 

 另个版本,这个版本INF一定要long long 才能过,为什么啊??
#include 
#include

#include

#include

#include

#define INF (1LL<<62)
using namespace std;
typedef
long long ll;
typedef pair
int> P;
struct edge{
int to;
ll v;
edge(
int to,ll v):to(to),v(v){}
edge(){}
};
const int maxn = 100010;
const int maxe = 100010;
int V,E;
vector
g[maxn];
ll d[maxn],d2[maxn];
//最短距离和次短距离
void dijkstra(int s)
{
priority_queue
,greater

> pq;
for(int i=1;i<=V;i++)
{
d[i]
=INF;
d2[i]
=INF;
}
d[s]
=0;
pq.push(P(
0,s));
while(pq.size())
{
P nowe
=pq.top();pq.pop();
if(nowe.first>d2[nowe.second]) continue; //如果这个距离比当前次短路长continue
for(int v=0;v<(int)g[nowe.second].size();v++)
{
edge nexte
=g[nowe.second][v];
ll dis
=nowe.first+nexte.v;
if(d[nexte.to]>dis)
{
swap(dis,d[nexte.to]);
pq.push(P(d[nexte.to],nexte.to));
}
if(d2[nexte.to]>dis&&d[nexte.to]//保证最短路是小于这个次短路的
{
d2[nexte.to]
=dis;
pq.push(P(d2[nexte.to],nexte.to));
//次短路的点进入pq
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int TT;
scanf(
"%d",&TT);
while(TT--) {
int s;//起点
scanf("%d%d",&V,&E);
{
for(int i=1;i<=V;i++)
g[i].clear();
for(int i=1;i<=E;i++)
{
int f,t;
ll v;
scanf(
"%d%d%I64d",&f,&t,&v);
g[f].push_back(edge(t,v));
g[t].push_back(edge(f,v));
}
s
=1;//这题默认起点为1
dijkstra(s);
printf(
"%I64d\n",d2[V]);
}
}
return 0;
}

 


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文介绍了一道网络流题目hdu4888 Redraw Beautiful Drawings的解题思路。题目要求以行和列作为结点建图,并通过最大流算法判断是否有解以及是否唯一。文章详细介绍了建图和算法的过程,并强调在dfs过程中要进行回溯。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
author-avatar
小力维2010_622_531
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有