P神的SDFZ考试题 C题
探险
【问题描述】
探险家小 T 好高兴! X 国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品
哦!小 T 虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过!
比赛即将开始,工作人员说明了这次比赛的规则:每个溶洞和其他某些溶洞
有暗道相连。两个溶洞之间可能有多条道路,也有可能没有,但没有一条暗道直
接从自己连到自己。参赛者需要统一从一个大溶洞出发,并再次回到这个大溶洞。
如果就这么点限制,那么问题就太简单了,可是举办方又提出了一个条件:
不能经过同一条暗道两次。这个条件让大家犯难了。这该怎么办呢?
到了大溶洞口后,小 T 愉悦地发现这个地方他曾经来过,他还记得有哪些
暗道,以及通过每条暗道的时间。小 T 现在向你求助,你能帮他算出至少要多
少时间才能回到大溶洞吗?(起点编号为 1)
【输入格式】
第一行两个数 n , m 表示溶洞的数量以及暗道的数量。
接下来 m 行,每行 4 个数 s 、 t 、 w 、 v,表示一个暗道连接的两个溶洞 s 、 t,
这条暗道正着走(s à t)的所需要的时间 w,倒着走(t à s)所需要的时间 v。
由于溶洞的相对位置不同,w 与 v 可能不同。
【输出格式】
输出一行一个数 t,表示最少所需要的时间。
【样例输入】
3 3
1 2 2 1
2 3 4 5
3 1 2 3
【样例输出】
8
这又是一道bzoj的权限题
首先这个题可以打一个暴力的写法:
枚举从一号节点出发第一个走的溶洞,再强行把那条边断开,然后求那个溶洞到一号节点的最短路相加
好像这样是能过的样子
正解有一个极其鬼畜的建图根本看不懂(其实就算看懂了以后也想不出来)
于是P神还有一个一句话嘴巴AC的正解
在spfa的时候维护到一个点的最短路和次短路并且保证最短路和次短路的第一条边不一样,
然后再枚举和1相连的边回去即可
(优先考虑最短路+这条边,如果发现最短路的第一条边和这条边相同,就用次长边+这条边(次长边和最长边的第一条边不同)
Orz Orz跪地膜啊,简单粗暴
但不过这个东西的if打得是真的操蛋啊
其实理清楚了,也就是想写数学大题的分类讨论吧
附上巨丑代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1000050;
const int Inf=20010411;
int gi(){
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
int cnt=1,n,m,head[N],to[N],nxt[N],c[N],in[N],vis[N],ans=Inf,vis2[N];
int W[N];
struct Data{
int first,second,ffrom,sfrom;
}dis[N];
struct data{
int x,fa,from;
}q[N*2];
void lnk(int x,int y,int v,int z){
to[++cnt]=y,c[cnt]=v,nxt[cnt]=head[x],head[x]=cnt;
to[++cnt]=x,c[cnt]=z,nxt[cnt]=head[y],head[y]=cnt;
}
void spfa(){
int t=0,sum=1;q[0].x=1;dis[1].first=dis[1].second=0;
while(t<sum){
data now=q[t++];
for(int i=head[now.x];i;i=nxt[i]){
if(i!=(now.fa^1)||now.fa==0){
int y=to[i],flag=0;
/*//我们不妨定义xf,xs,yf,ys表示这四条路径长度的鬼畜关系
//先确定长度后再转移
//首先我们知道 xf<xs和yf<ys;
//下面把所有情况列举下来:
//1.xf<yf<xs<ys
//2.xf<yf<ys<xs
//3.xf<xs<yf<ys
//4.xf<xs<yf<ys
//-------------------
//5.yf<xf<xs<ys
//6.yf<xf<ys<xs
//7.yf<ys<xf<xs*/
if(now.x!=1){
if(dis[now.x].first+c[i]<dis[y].first){
//当前更新的路比y的最短路还要短,那么y的最短路一定会被更新,次短路可能会更新
if(dis[y].first<dis[now.x].second+c[i]){
//xf<yf<(xs,ys未知)
if(dis[y].ffrom!=dis[now.x].ffrom){
//xf和yf的第一条边不同,又已知yf和ys的第一条边不会一样
//那么xs不需要考虑
//转移:ys=yf,yf=xf
dis[y].second=dis[y].first;dis[y].sfrom=dis[y].ffrom;
dis[y].first=dis[now.x].first+c[i];dis[y].ffrom=dis[now.x].ffrom;
flag=1;
}
else{
//xf和yf的第一条边相同,yf必定要变成xf的,我们要考虑xs怎么变
//1.xf<yf<ys<xs,那么ys保持不变
if(dis[y].second<dis[now.x].second){
dis[y].first=dis[now.x].first+c[i];
dis[y].ffrom=dis[now.x].ffrom;
flag=1;
}
//2.xf<yf<xs<ys
else{
//如果yf和xs的第一条边不同
//yf=xf,ys=xs;
if(dis[y].ffrom!=dis[now.x].sfrom){
dis[y].first=dis[now.x].first+c[i];
dis[y].ffrom=dis[now.x].ffrom;
dis[y].second=dis[now.x].second+c[i];
dis[y].sfrom=dis[now.x].sfrom;
flag=1;
}
}
}
}
else{//xf<xs<yf<ys,这么好打的一个我竟然忘记了
//这个最理想了直接yf=xf,ys=xs
dis[y].first=dis[now.x].first+c[i];
dis[y].ffrom=dis[now.x].ffrom;
dis[y].second=dis[now.x].second+c[i];
dis[y].sfrom=dis[now.x].sfrom;
}
}
else {//现在是yf<xf
//yf<(xf<xs,ys)未知,那么yf是不能被更新了吧
//1.yf<xf<ys<xs;
if(dis[y].second<dis[now.x].second+c[i]&&dis[y].second>dis[now.x].first+c[i]){
if(dis[y].ffrom!=dis[now.x].ffrom){//yf和xf的第一条边没有冲突,ys=xf;
dis[y].second=dis[now.x].first+c[i];
dis[y].sfrom=dis[now.x].ffrom;
flag=1;
}
}
//2.yf<ys<xf<xs 根本不需要更新
//3.yf<xf<xs<ys;
else if(dis[y].second>dis[now.x].second+c[i]){
if(dis[y].ffrom!=dis[now.x].ffrom){//优先考虑xf来更新
dis[y].second=dis[now.x].first+c[i];
dis[y].sfrom=dis[now.x].ffrom;
flag=1;
}
else if(dis[y].ffrom!=dis[now.x].sfrom){
dis[y].second=dis[now.x].second+c[i];
dis[y].sfrom=dis[now.x].sfrom;
flag=1;
}
}
}
}
if(flag||now.x==1){
q[sum++]=(data){y,i};
}
}
}
}
}
int main(){
freopen("exp.in","r",stdin);
freopen("exp.out","w",stdout);
n=gi(),m=gi();
for(int i=1;i<=m;i++){
int x=gi(),y=gi(),v=gi(),z=gi();
lnk(x,y,v,z);
}
for(int i=2;i<=n;i++) dis[i].first=dis[i].second=Inf;
for(int i=head[1];i;i=nxt[i]){
if(dis[to[i]].first==Inf){
dis[to[i]].first=c[i];
dis[to[i]].ffrom=i;
}
else{
if(dis[to[i]].first>c[i]){
dis[to[i]].second=dis[to[i]].first;
dis[to[i]].sfrom=dis[to[i]].ffrom;
dis[to[i]].first=c[i];
dis[to[i]].ffrom=i;
}
else{
if(dis[i].second>c[i]){
dis[to[i]].second=c[i];
dis[to[i]].sfrom=i;
}
}
}
}
spfa();
for(int i=head[1];i;i=nxt[i]){
int y=to[i];
if(dis[y].ffrom!=i) ans=min(ans,dis[y].first+c[i^1]);
else ans=min(ans,dis[y].second+c[i^1]);
}
printf("%d",ans);
}
P神的SDFZ考试题 C题的更多相关文章
- 刷题向》关于一道尺取法的神题目(BZOJ4653)(HARD-)(BZOJ 30题纪念)
不得不说,这也许会是一道长期在我的博客里作为“HARD”难度存在的题 这道题能很好的考验选手的思考能力,但本蒟蒻最后还是听了省队爷讲了之后才会...(默默面壁) 题目里,说对于每一个点,是用当前选出的 ...
- csu 10月 月赛 H 题 A Very Hard Problem
Description CX老湿经常被人黑,被黑得多了,自己也就麻木了.于是经常听到有人黑他,他都会深情地说一句:禽兽啊! 一天CX老湿突发奇想,给大家出了一个难题,并且声称谁能够准确地回答出问题才能 ...
- [BJOI2019]勘破神机
[BJOI2019]勘破神机 推式子好题 m=2,斐波那契数列,$f_{n+1}$项 不妨$++l,++r$,直接求$f_n$ 求$\sum C(f_n,k)$,下降幂转化成阶乘幂,这样都是多项式了, ...
- C++笔试易错题集(持续更新)
1.如下代码输出结果是什么? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include<stdio.h> char *myString() { ...
- 【BZOJ4916】神犇和蒟蒻 解题报告
[BZOJ4916]神犇和蒟蒻 Description 很久很久以前,有一群神犇叫sk和ypl和ssr和hjh和hgr和gjs和yay和xj和zwl和dcx和lyy和dtz和hy和xfz和myh和yw ...
- Python基础数据类型题
Python基础数据类型 题考试时间:三个小时 满分100分(80分以上包含80分及格)1,简述变量命名规范(3分) 1.必须是字母,数字,下划线的任意组合. 2.不能是数字开头 3.不能是pytho ...
- Codeforces数据结构(水题)小结
最近在使用codeblock,所以就先刷一些水题上上手 使用codeblock遇到的问题 1.无法进行编译-------从setting中的编译器设置中配置编译器 2.建立cpp后无法调试------ ...
- [日常] NOIP前集训日记
写点流水账放松身心... 10.8 前一天考完NHEEE的一调考试终于可以开始集训了Orz (然后上来考试就迟到5min, GG) T1维护队列瞎贪心, 过了大样例交上去一点也不稳...T出翔只拿了5 ...
- PKUSC2016
day x(x<0) 外出培训倒数第二天晚上发烧了....逃过了第二天早上的考试,orz 抢到rank 1 的commonc神犇!! day 0 下午到了北大,发了两张50元饭卡.这是第三次来北 ...
随机推荐
- JAVA基础5——与String相关的系列(2)
差异点比较 String使用+直接拼接 这种情况需要分两种情况来讨论: 1. 都是确定的字符串常量之间进行的+号拼接的时候,由于在编译器就可以确定其具体值了,所以编译器在编译期的时候就会把这些常量拼接 ...
- 2807:两倍-poj
2807:两倍 总时间限制: 1000ms 内存限制: 65536kB 描述 给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍. 比如给定1 4 ...
- 【原创】通过搬瓦工vps搭建SS环境,供学习用
博主前段时间处于某些不可告人的目的,但又限于各类科学工具被禁的窘境,用搬瓦工的vps搭建了次SS环境,现在就来回顾并不知廉耻的传授下经验. 第一步:购买vps 1.登录官网 https://bwh1. ...
- ThinkPHP中的Model模型
一 实例化模型对象 ①实例化通用模型 例:$goods_model = new \Model\GoodsModel(); $goods_Model = D('Goods'); ②实例化基例模型 ...
- apache编译安装 httpd 2.2 httpd 2.4
#apache编译安装#httpd 2.2 , httpd 2.4 #!/bin/sh #apache编译安装 #httpd 2.2 , httpd 2.4 #centos #rpm -e httpd ...
- Python测试开发之---list、str、dict、tuple小结
str的常用方法有: str.digits 0-9的表示str.uppercase 大写字母str.lowercase 小写字母str.letters 所有字母" ".join(s ...
- codeforces 893B Beautiful Divisors 打表
893B Beautiful Divisors 思路: 打表 代码: #include <bits/stdc++.h> using namespace std; #define _for( ...
- 深度解剖sesssion运行原理
已经大半年没有更新博客了,一方面有比博客更重要的事情要做,另外一方面也没有时间来整理知识,所以希望在接下来的日子里面能够多多的写博客来与大家交流 什么是session session的官方定义是:Se ...
- loadrunner 参数存储在data.ws、paralist、globals.h 中区别(参数与变量额区别于使用)
1.如果变量数据只有一个值,可以直接放在data.ws 中 2.如果变量要根据循环取随机值.序列值等(参数存在一组值),放在paralist中 3.如果是申明全局变量,且要在代码中用到参 ...
- HttpClient4.2 Fluent API学习
相比于HttpClient 之前的版本号,HttpClient 4.2 提供了一组基于流接口(fluent interface)概念的更易使用的API,即Fluent API. 为了方便使用,Flue ...