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元饭卡.这是第三次来北 ...
随机推荐
- day01_HTML
今日任务 网站信息页面案例 网站图片信息页面案例 网站友情链接页面案例 网站首页案例 网站后台页面案例 教学目标 了解什么是标记语言 了解HTML的框架标签 掌握HTML的主要标签(字体,图片,列表, ...
- PHP时间戳和日期互转换
在php中我们要把时间戳转换日期可以直接使用date函数来实现,如果要把日期转换成时间戳可以使用strtotime()函数实现,下面我来给大家举例说明. 1.php中时间转换函数 strtotime ...
- Servlet之会话(Session)以及会话追踪技术(Cookie),(URL重写)和(隐藏表单域)
Session 什么是会话? 会话: Web应用中的会话 指的是一个客户端浏览器与Web服务器之间连续发生的一系列请求和响应的过程 会话状态: Web服务器和浏览器在会话的过程中产生的状态信息 作用: ...
- robotframework文本类型的下拉框
对于下拉框定位和输入,这里主要遇到有两种类型的下拉选择. 其中一个类型是select-options格式,如图 这种方式的定位可以使用select from list by value或select ...
- 【转】用systemJS+karma+Jasmine+babel环境去编写简单的ES6工程
原文链接:http://www.cnblogs.com/shuoer/p/7779131.html 用systemJS+karma+Jasmine+babel环境去编写简单的ES6工程 首先解释下什么 ...
- apache通过AD验证
## apache通过AD验证 #yum install httpd mod_authz_ldap#安装apahce的ldap模块yum install mod_authz_ldap -y #配置ap ...
- springboot集成swagger
对于搬砖的同学来说,写接口容易,写接口文档很烦,接口变动,维护接口文档就更更更烦,所以经常能发现文档与程序不匹配. 等过一段时间就连开发者也蒙圈了 Swagger2快速方便的解决了以上问题.一个能与S ...
- unity中调用其他脚本函数的方法(小白之路)
第一种,被调用脚本函数为static类型,调用时直接用 脚本名.函数名().很不实用-- 第二种,GameObject.Find("脚本所在物体名").SendMessage(& ...
- zzuli 2131 Can Win dinic+链式前向星(难点:抽象出网络模型+建边)
2131: Can Win Time Limit: 1 Sec Memory Limit: 128 MB Submit: 431 Solved: 50 SubmitStatusWeb Board ...
- Nodejs学习笔记(十七)--- 浮点运算decimal.js
目录 前言 JavaScript加减乘除运算 decimal.js加减乘除运算 前言 开发过程中免不了有浮点运算,JavaScript浮点运算的精度问题会带来一些困扰 JavaScript 只有一种数 ...