826. [Tyvj Feb11] GF打dota

★★☆   输入文件:dota.in   输出文件:dota.out   简单对比
时间限制:1 s   内存限制:128 MB

众所周知,GF同学喜欢打dota,而且打得非常好。今天GF和Spartan同学进行了一场大战。

现在GF拿到一张地图,地图上一共有n个地点,GF的英雄处于1号点,Spartan的基地位于n号点,

GF要尽快地选择较短的路线让他的英雄去虐掉Spartan的基地。但是Spartan早就料到了这一点,

他有可能会开挂(BS~)使用一种特别的魔法,一旦GF所走的路线的总长度等于最短路的总长度时,

GF的英雄就要和这种魔法纠缠不休。这时GF就不得不选择非最短的路线。现在请你替GF进行规划。

对于描述的解释与提醒:
1.无向路径,花费时间当然为非负值。

2.对于本题中非最短路线的定义:不管采取任何迂回、改道方式,

只要GF所走的路线总长度不等于1到n最短路的总长度时,就算做一条非最短的路线。

3.保证1~n有路可走。

输入:

第一行为n,m(表示一共有m条路径)
接下来m行,每行3个整数a,b,c,表示编号为a,b的点之间连着一条花费时间为c的无向路径。
接下来一行有一个整数p,p=0表示Spartan没有开挂使用这种魔法,p=1则表示使用了。

输出:

所花费的最短时间t,数据保证一定可以到达n。

样例输入1:
5 5
1 2 1
1 3 2
3 5 2
2 4 3
4 5 1
0

样例输入2:
5 5
1 2 1
1 3 2
3 5 2
2 4 3
4 5 1
1

 
样例输出1:
4
样例输出2:
5

对于50%的数据,1<=n,m<=5000
对于70%的数据,1<=n<=10000, 1<=m<=50000,p=0,
对于100%的数据,1<=n<=10000, 1<=m<=50000,p=1
无向图,花费时间c>=0

各个测试点1s

 
来源:lydliyudong    Tyvj February二月月赛第二场  第2道

敬爱的读者:在这里抱歉地声明 接下来的一大段呕心沥血的讲解皆为不完全正确的

我一度认为 用一个dis2数组来表示从根节点到每一个点的次短路的值

但是经过认真思考 和跌坑儿后  我发现 不能这样子去做

求出对于一个点的次短路 并不能向另外的一个点去扩展

所以下面的内容仅做思维拓展(只有70分,我下面这个冒险的自创算法有不正确的情况存在!)

这一道题真的是太难了额,发现自己最近总是冲动想要自己去研究一些没学过的东西

那么怎样子用dijkstra来解决这一道坑人的题呢?

首先我们先来回忆一下dijkstra最短路是怎样求的

就是利用一个优先队列 往里面放一个个pair <dis[x],x> 去一个个松弛

那么求次短路怎么办呢?

突然间 我想到了一个异常暴力的做法

就是说 最短路肯定是整张图中最优最优的路径了 随便改变一下路径上的那一条边都不是最短路了

那么我们可以枚举一下删掉哪一条边 每一次跑一遍在删掉当前所枚举的边后的新图上跑dijkstra

很显然这个想法是非常正确的 也是没有什么意义的 因为这肯定效率非常的低下啊

所以我们要来想一种办法 使得在跑最短路的同时求出次短路?!?<<这真是一个神奇又看起来不太可能的想法

原来不是有一个数组是dis数组 来记录每一个点到根节点最短路的长度

那么我们再来设一个dis2数组 当然非常显然针对这一道题是没有什么很大的必要的

但是这样子可能会对我们以后解决一些比较共性的问题会有很大的帮助的♪(^∇^*)

经过10分钟的沉思 我终于想出了一种解决办法

您这么想:

我们再进行松弛操作的时候是从小到大的

有以下这么几种情况

1.现在枚举的dis[y]+v[x][i]<dis2[x]

也就是说 找到了更短的次短路 就swap一下

2.dis2[x]<dis1[x]

也就是说次短路比最短路还要短

那次短路和最短路 调一个个儿就行了

那么怎么证明上面的方法是正确的呢?

首先你第一个枚举的肯定是最小的对吧

你会在第一次循环中先把dis2更新

现在的dis2比dis1小 就swap一下  那么当前的最短路就是当前枚举的  次短路还是正无穷

其实这样子讲还是太抽象了

首先看第一个情况 更新次短路 这肯定是没有什么问题了 有更短的就更新一下 很正确啊

第二个情况呢?

如果dis2<dis1 就swap    对于最短路肯定是没有问题的 这样子dis1就成了枚举到当前时 的最短路

其实dis2的正确性也是可以保证的 因为dis1是原来先前所有情况中最短的   现在往后顺移 就成了第二短的 没有任何问题!

所以我们就可以付诸实施这个本人自己想出来的绝妙办法 啦

可惜只有70分 WA了30

#include<bits/stdc++.h>
#define maxn 10005
#define maxm 50005
#define pa pair<int,int>
using namespace std;
int n,m;
vector<int> v[maxn],w[maxn];
int dis1[maxn],dis2[maxn];
int vis[maxn];
priority_queue<pa,vector<pa>,greater<pa> > q;
void Dijkstra()
{
memset(dis1,0x3f,sizeof(dis1));
memset(dis2,0x3f,sizeof(dis2));
dis1[]=;
dis2[]=;
q.push(make_pair(,));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis[x])
continue;
vis[x]=;
for(int i=;i<v[x].size();i++)
{
int y=v[x][i];
if(dis2[y]>dis1[x]+w[x][i])
dis2[y]=dis1[x]+w[x][i];
if(dis2[y]<dis1[y])
swap(dis2[y],dis1[y]);
q.push(make_pair(dis1[y],y));
}
}
}
int main()
{
freopen("dota.in","r",stdin);
freopen("dota.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
v[x].push_back(y);
v[y].push_back(x);
w[x].push_back(z);
w[y].push_back(z);
}
Dijkstra();
int p;
scanf("%d",&p);
if(p)
printf("%d",dis2[n]);
else
printf("%d",dis1[n]);
return ;
}

这是70分的代码

经过3天的苦苦思考 我仿佛想出了一个反例

就是说如果按照我上面的做法 可能会出现 一种情况

就是 求出来的次短路和最短路的数值是相同的

比如有两条路径走出来都是4

那么最短路和次短路答案就都成了4

非常的苦闷

 现在我们还是来正八经儿地讲一下比较普遍认可的做法吧(我太蒟了 自创了一个算法错了)

好 ,这一道题的正解是

跑两边dijkstra  是不是非常的荒唐?

就是以1为根正着来一遍 以n为根反着来一遍

正着的是dis1数组 反着的是dis2数组 我们可以发现

我们可以枚举每一条边

这一条边的两个端点是u v

u比较靠近1  v比较靠近n

那么我们只要找到最小的不等于最短路的次短路即可

就是dis1[u]+边权+dis2[v]中取一个最小的即可

然而 还是70分  严重抗议!这一道题有问题吧~

#include<bits/stdc++.h>
#define maxn 10005
#define pa pair<int,int>
using namespace std;
int vis1[maxn],vis2[maxn],vis3[maxn],dis1[maxn],dis2[maxn];
priority_queue<pa,vector<pa>,greater<pa> > q;
vector<int> v[maxn],w[maxn];
int n,m;
void Dijkstra1()
{
memset(dis1,0x3f,sizeof(dis1));
dis1[]=;
q.push(make_pair(,));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis1[x])
continue;
vis1[x]=;
for(int i=;i<v[x].size();i++)
{
int y=v[x][i];
if(dis1[y]>dis1[x]+w[x][i])
{
dis1[y]=dis1[x]+w[x][i];
q.push(make_pair(dis1[y],y));
}
}
}
}
void Dijkstra2()
{
memset(dis2,0x3f,sizeof(dis2));
dis2[n]=;
q.push(make_pair(,));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis2[x])
continue;
vis2[x]=;
for(int i=;i<v[x].size();i++)
{
int y=v[x][i];
if(dis2[y]>dis2[x]+w[x][i])
{
dis2[y]=dis2[x]+w[x][i];
q.push(make_pair(dis2[y],y));
}
}
}
}
int Min=0x3f3f3f3f;
void Dfs(int x)
{
if(vis3[x])
return;
vis3[x]=;
for(int i=;i<v[x].size();i++)
{
int y=v[x][i];
int Dis=dis1[x]+w[x][i]+dis2[y];
if(Dis!=dis1[n]&&Dis<Min)
Min=Dis;
Dfs(y);
}
}
int main()
{
freopen("dota.in","r",stdin);
freopen("dota.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
v[x].push_back(y);
v[y].push_back(x);
w[x].push_back(z);
w[y].push_back(z);
}
Dijkstra1();
int p;
scanf("%d",&p);
if(p==)
{
printf("%d",dis1[n]);
return ;
}
Dijkstra2();
Dfs();
printf("%d",Min);
return ;
}

已然是70分 谁来救救我啊

下面上一个神奇的满分做法 A*

#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>//系统快排必加
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
const int maxn=;
int n,m,dis[maxn];vector<int>son[maxn],v[maxn];
bool bein[maxn];queue<int>q;
void Set(int prt,int to,int d){
son[prt].push_back(to),v[prt].push_back(d);
}
void spfa(int s){
memset(dis,0x3f,sizeof(dis));
dis[s]=,q.push(s),bein[s]=true;
while(!q.empty()){
int rt=q.front();q.pop(),bein[rt]=false;
for(int i=;i<son[rt].size();i++){
int to=son[rt][i];
if(dis[to]>dis[rt]+v[rt][i]){
dis[to]=dis[rt]+v[rt][i];
if(!bein[to])bein[to]=true,q.push(to);
}
}
}
}
struct node{
int x,d;
bool operator<(const node &a)const{
return d+dis[x]>a.d+dis[a.x];
}
};priority_queue<node>Q;
int Astar(int s,int t){
Q.push((node){s,});
while(!Q.empty()){
node prt=Q.top();Q.pop();int rt=prt.x;
if(rt==t&&prt.d>dis[s])return prt.d;
for(int i=;i<son[rt].size();i++)
Q.push((node){son[rt][i],prt.d+v[rt][i]});
}
}
int main()
{
freopen("dota.in","r",stdin);
freopen("dota.out","w",stdout);
int x,y,z,p;
cin>>n>>m;
int i;
while(m--)
cin>>x>>y>>z,Set(x,y,z),Set(y,x,z);
spfa(n);
cin>>p;
if(p==)
cout<<dis[];
else
cout<<Astar(,n);
return ;
}

cogs 826. [Tyvj Feb11] GF打dota 次短路详细原创讲解! dijkstra的更多相关文章

  1. cogs 826. [Tyvj Feb11] GF打dota

    826. [Tyvj Feb11] GF打dota ★★☆   输入文件:dota.in   输出文件:dota.out   简单对比时间限制:1 s   内存限制:128 MB 众所周知,GF同学喜 ...

  2. COGS——T 826. [Tyvj Feb11] GF打dota

    http://www.cogs.pro/cogs/problem/problem.php?pid=826 ★★☆   输入文件:dota.in   输出文件:dota.out   简单对比时间限制:1 ...

  3. COGS 1191. [Tyvj Feb11] 猫咪的进化

    ★   输入文件:neko.in   输出文件:neko.out   简单对比时间限制:1 s   内存限制:128 MB [背景] 对于一只猫咪来说,它是有九条命的.但是并不是所有的猫咪都是这样,只 ...

  4. COGS 827. [Tyvj Feb11] 网站计划

    输入文件:web.in   输出文件:web.out   简单对比时间限制:1 s   内存限制:128 MB 描述 Description     Tyvj的Admin--zhq同学将在寒假开始实行 ...

  5. [TYVJ] P1423 GF和猫咪的玩具

    GF和猫咪的玩具 描述 Description GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金 ...

  6. COGS 1215. [Tyvj Aug11] 冗余电网

    ★   输入文件:ugrid.in   输出文件:ugrid.out   简单对比时间限制:1 s   内存限制:128 MB TYVJ八月月赛提高组第2题 测试点数目:5 测试点分值:20 --内存 ...

  7. cogs——1215. [Tyvj Aug11] 冗余电网

    1215. [Tyvj Aug11] 冗余电网 ★   输入文件:ugrid.in   输出文件:ugrid.out   简单对比 时间限制:1 s   内存限制:128 MB TYVJ八月月赛提高组 ...

  8. cogs 1829. [Tyvj 1728]普通平衡树 权值线段树

    1829. [Tyvj 1728]普通平衡树 ★★★   输入文件:phs.in   输出文件:phs.out   简单对比时间限制:1 s   内存限制:1000 MB [题目描述] 您需要写一种数 ...

  9. tyvj 1423 GF和猫咪的玩具

    传送门 解题思路 题目比较水,floyd求出最短路取个最小值即可.结果joyoi时限写错了..好像只有0ms才能过??突然发现加了快读就T不加就A,数据在10000以下的还是scanf快啊. 代码 # ...

随机推荐

  1. CodeForces 1204E"Natasha, Sasha and the Prefix Sums"(动态规划 or 组合数学--卡特兰数的应用)

    传送门 •参考资料 [1]:CF1204E Natasha, Sasha and the Prefix Sums(动态规划+组合数) •题意 由 n 个 1 和 m 个 -1 组成的 $C_{n+m} ...

  2. Python--day32--ftp文件传输报错的原因

    解决办法:把buffer改小 server.py #实现一个大文件的上传或下载 #配置文件 ip地址 端口号 import json import socket import struct sk = ...

  3. 2019-1-27-WPF-使用-ItemsPanel-修改方向

    title author date CreateTime categories WPF 使用 ItemsPanel 修改方向 lindexi 2019-1-27 21:8:9 +0800 2019-0 ...

  4. linux 系统挂起

    尽管内核代码的大部分 bug 以 oops 消息结束, 有时候它们可能完全挂起系统. 如果系 统挂起, 没有消息打印. 例如, 如果代码进入一个无限循环, 内核停止调度,[15]15 并且系 统不会响 ...

  5. win10 uwp 解决 SerialDevice.FromIdAsync 返回空

    调用 SerialDevice.FromIdAsync 可能返回空,因为没有设置 package.appmanifest 可以使用端口 打开 package.appmanifest 文件添加下面代码 ...

  6. asp.net core 3.0 JObject The collection type 'Newtonsoft.Json.Linq.JObject' is not supported

    在asp.net core 3.0 中,如果直接在Controller中返回 Jobject 类型,会抛出如下错误: The collection type 'Newtonsoft.Json.Linq ...

  7. Java中大量if...else语句的消除替代方案

    在我们平时的开发过程中,经常可能会出现大量If else的场景,代码显的很臃肿,非常不优雅.那我们又没有办法处理呢? 针对大量的if嵌套让代码的复杂性增高而且难以维护.本文将介绍多种解决方案. 案例 ...

  8. 使用FluentEmail发送outlook邮件

    一,邮箱账号相关设置 1,创建outLook邮箱. 2,进入邮箱设置->同步电子邮件->允许设备和应用使用pop 3,设置microsoft账号的应用程序密码->进入安全性页面-&g ...

  9. Checkpoint R77.30 web ui登录配置

    R77.30默认只能使用微软内核的浏览器进行web ui的登陆,在专家模式下修改后chrome和firefox正常登录,步骤如下: [Expert@BJ-ZHX-FW:0]# cp /web/htdo ...

  10. .NET ORM 开源项目 FreeSql 1.0 正式版发布

    一.简介 FreeSql 是 .NET 平台下的对象关系映射技术(O/RM),支持 .NetCore 2.1+ 或 .NetFramework 4.0+ 或 Xamarin. 从 0.0.1 发布,历 ...