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元饭卡.这是第三次来北 ...
随机推荐
- 作为新手 HTML5如何自学为好?
互联网发展到今天,越来越多的技术岗位人才出现了稀缺的状态,就拿当前的HTML5来讲,基本成为了每家互联网公司不可缺少的人才.如果抓住这个机会,把HTML5搞好,那么前途不可限量,而且这门行业是越老越吃 ...
- 多服务器操作利器 - Polysh
多台服务器下的痛苦人生 分布式架构下的系统,可以说每个服务都是分别部署在多台服务器上的,有的甚至还需要多机房,在这种架构下可以说可以很好的做到了易扩展.容灾等功能.推荐的服务部署为一服务多机器.一机器 ...
- (ajax)——jquery用法
例子:/* ajax获得状态 */ 点击事件 $("#findBycname").click(function(){ var company = ...
- CCF考试认证模拟练习——数字排序
#include<iostream>#include<algorithm>using namespace std;struct node //定义结构体{ int num;// ...
- 设置SO_RECVBUF和SO_SENDBUF套接字选项
控制套接字的行为(如修改缓冲区的大小). int getsockopt(int sockfd,int level,int optname,void *optval,socklen_t *optlen) ...
- Libevent 事件循环(2)---事件被加入激活队列
由Libevent 事件循环(1) 在上文中我们提到了libevent 事件循环event_dispatch 的大致过程,以epoll为例,我们看一下事件被如何加入激活队列. //在epoll_dis ...
- HDU1541--Stars(树状数组)
Stars Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- 删除kafka的topic及kafka基本命令
kafka的topic默认是不允许被删除的,删除后在topic后会出现”marked for deletion”字样,实际并未删除,现在创建同样的topic会提示topic已经存在. 解决办法: se ...
- PHP如何强制下载文件
很多网站都需要做文件下载的功能.如果直接给连接的方式下载的话有很多的弊处...因为有时候需要对下载权限的检查,对下载次数的检查.所以一般采用php的方法进行安全下载.但是下载的时候如果是txt jpg ...
- django.db.utils.OperationalError: 1050解决方案
manage.py migrate时进行同步数据库时出现问题;django.db.utils.OperationalError: (1050, "Table '表名' already exi ...