题目大意:https://www.cnblogs.com/Juve/articles/11219089.html

那一天,我们......行啦,不要帮出题人脑补画面了,我们来正经的题解

我们发现我们可以把与1号节点相连的所有节点取出,如果我们把最小环在1号节点处断开,那么最小环断成的链一定是以这些节点中的某一个节点作为起点,另一个节点作为终点的一条路路径。
如果不考虑时间复杂度,我们完全可以枚举作为起点的节点,每次都跑一遍最短路来更新答案。
但是上面的做法肯定会爆炸,所以我们考虑如何降低复杂度。

我们考虑把所有的节点分为两组,一组中的所有点作为起点,另一组中的所有点作为终点,一起跑最短路,更新答案。
如此我们发现只要我们能够保证真正贡献答案的一对节点会在某一次分组当中被分到不同组,我们就可以保证算法的正确性。
因为起点与终点的编号肯定不相同,于是我们可以按照二进制分组,枚举每个二进制位,按照当前二进制位的0/1情况来进行分组。

我看好像没有人用这种方法的,其实dij就可以过,用dij求1号节点开始的最小环

别告诉我你不会求最小环。

我们枚举1号点连接的每一条边,设起点为fr[i],终点为to[i],

先把这条边权变成0x3f3f3f3f,跑dij,求出此时fr[i]到to[i]的最短路,再加上原来这条边的权值就是一个环的大小,

更新答案:ans=min(dis[to[i]]+w[i]);

就是把fr[i]和to[i]间的边断开后两点间的最短路加上原来两点间的距离取最小值

原来博主想用tarjan求边双,然后在1号节点所在的边双中跑dij,但时间并没有下去

还有注意给边编号从2开始,这样i和i^1是一对双向边

本来一道很有思维量的题被做成了dijkstra模板(好像没人用正解打)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
#define MAXN 10005
#define MAXM 40005
using namespace std;
ll t,n,m,ans=0x3f3f3f3f;
ll pre[MAXN],tot_e=1,to[MAXM<<1],nxt[MAXM<<1],w[MAXM<<1];
void add(ll u,ll v,ll d){
tot_e++,to[tot_e]=v,nxt[tot_e]=pre[u],pre[u]=tot_e,w[tot_e]=d;
}
ll dis[MAXN];
priority_queue< pair<ll, ll> > q;
bool visit[MAXN];
void dijkstra(ll x){
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
memset(visit,0,sizeof(visit));
q.push(make_pair(-dis[x],x));
while(!q.empty()){
ll y=q.top().second;q.pop();
if(visit[y]) continue;
visit[y]=1;
for(ll i=pre[y];i;i=nxt[i]){
ll v=to[i],z=w[i];
if(dis[v]>dis[y]+z){
dis[v]=dis[y]+z;
q.push(make_pair(-dis[v],v));
}
}
}
}
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
for(ll i=1,u,v,d;i<=m;i++){
scanf("%lld%lld%lld",&u,&v,&d);
add(u,v,d),add(v,u,d);
}
for(ll i=pre[1];i;i=nxt[i]){
ll temp=w[i];
w[i]=w[i^1]=0x3f3f3f3f;
dijkstra(1);
ans=min(ans,dis[to[i]]+temp);
w[i]=w[i^1]=temp;
}
if(ans==0x3f3f3f3f) ans=-1;
printf("%lld\n",ans);
ans=0x3f3f3f3f;
tot_e=1;
memset(pre,0,sizeof(pre));
}
return 0;
}
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
#define MAXN 10005
#define MAXM 40005
using namespace std;
ll t,n,m,ans=0x3f3f3f3f;
ll pre[MAXN],tot_e=,to[MAXM<<],nxt[MAXM<<],w[MAXM<<];
void add(ll u,ll v,ll d){
tot_e++,to[tot_e]=v,nxt[tot_e]=pre[u],pre[u]=tot_e,w[tot_e]=d;
}
bool vis[MAXM<<];
void dfs(ll x,ll res){
if(res>ans) return ;
if(x==){
if(res!=){
ans=min(ans,res);
return ;
}
}
for(ll i=pre[x];i;i=nxt[i]){
if(!vis[i]){
vis[i]=,vis[i^]=;
dfs(to[i],res+w[i]);
vis[i]=,vis[i^]=;
}
}
}
ll dfn[MAXN],low[MAXN],dfs_order=;
bool is_bridge[MAXM<<];
void tarjan(ll x,ll in_edge){
dfn[x]=low[x]=++dfs_order;
for(ll i=pre[x];i;i=nxt[i]){
ll y=to[i];
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>low[x])
is_bridge[i]=is_bridge[i^]=;
}
else if(i!=(in_edge^))
low[x]=min(low[x],dfn[y]);
}
}
bool belong[MAXN];
void DFS(int x){
belong[x]=;
for(int i=pre[x];i;i=nxt[i]){
int y=to[i];
if(belong[y]||is_bridge[i]) continue;
DFS(y);
}
}
ll dis[MAXN];
priority_queue< pair<ll, ll> > q;
bool visit[MAXN];
void dijkstra(ll x){
memset(dis,0x3f,sizeof(dis));
dis[x]=;
memset(visit,,sizeof(visit));
q.push(make_pair(-dis[x],x));
while(!q.empty()){
ll y=q.top().second;q.pop();
if(visit[y]) continue;
visit[y]=;
for(ll i=pre[y];i;i=nxt[i]){
ll v=to[i],z=w[i];
if(dis[v]>dis[y]+z){
dis[v]=dis[y]+z;
q.push(make_pair(-dis[v],v));
}
}
}
}
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
if(n==m){
for(ll i=,u,v,d;i<=m;i++){
scanf("%lld%lld%lld",&u,&v,&d);
add(u,v,d),add(v,u,d);
}
dfs(,);
if(ans==0x3f3f3f3f) ans=-;
printf("%lld\n",ans);
ans=0x3f3f3f3f;
memset(pre,,sizeof(pre));
tot_e=;
}else{
for(ll i=,u,v,d;i<=m;i++){
scanf("%lld%lld%lld",&u,&v,&d);
add(u,v,d),add(v,u,d);
}
for(ll i=;i<=n;i++){
if(!dfn[i]) tarjan(i,);
}
DFS();
for(ll i=pre[];i;i=nxt[i]){
if(is_bridge[i]||!belong[to[i]]) continue;
ll temp=w[i];
w[i]=w[i^]=0x3f3f3f3f;
dijkstra();
ans=min(ans,dis[to[i]]+temp);
w[i]=w[i^]=temp;
}
if(ans==0x3f3f3f3f) ans=-;
printf("%lld\n",ans);
ans=0x3f3f3f3f;
tot_e=,dfs_order=;
memset(pre,,sizeof(pre));
memset(dfn,,sizeof(dfn));
memset(is_bridge,,sizeof(is_bridge));
}
}
return ;
}

tarjan的复杂算法

更多算法:

https://www.cnblogs.com/Juve/articles/11220105.html

HZOI2019 B. 那一天她离我而去 最小环的更多相关文章

  1. HZOI2019 A. 那一天我们许下约定 dp

    题目大意:https://www.cnblogs.com/Juve/articles/11219089.html 读这道题的题目让我想起了... woc我到底在想什么?好好写题解,现在不是干那个的时候 ...

  2. HZOI2019 超级树 dp

    题面:https://www.cnblogs.com/Juve/articles/11207540.html(密码)————————————————>>> 题解: 官方题解: 考虑d ...

  3. HZOI2019 砍树 整除分块

    题目链接:https://www.cnblogs.com/Juve/articles/11207540.html(密码你懂的)——————————>> 这题... 一开始想的二分,但此题不 ...

  4. HZOI2019 星际旅行 欧拉路

    题目大意:https://www.cnblogs.com/Juve/articles/11207540.html—————————> 题解:网上都是一句话题解:将所有的边拆成两条,问题变成去掉两 ...

  5. HZOI2019熟练剖分(tree)

    题目大意:https://www.cnblogs.com/Juve/articles/11186805.html 题解: 先给出官方题解: 其实这题跟期望没什么关系,因为E=$\sum_\limits ...

  6. HZOI2019建造游乐园(play)组合数学,欧拉图

    题目:https://www.cnblogs.com/Juve/articles/11186805.html(密码是我的一个oj用户名) solution: 反正我是想不出来... 题目大意就是要求出 ...

  7. HZOI2019序列

    题目链接:https://www.cnblogs.com/Juve/articles/11186805.html(密码是我的一个oj用户名) 题解: 这题我考试打的暴力,只有5分. 一开始理解错题意了 ...

  8. 【暑假集训】HZOI2019 Luogu P1006 传纸条 二三四维解法

    写三次丢失两次,我谔谔,以后再不在博客园先保存我就去死 题目内容 洛谷链接 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学被安排坐成一个\(m\)行.\(n\ ...

  9. 【暑假集训】HZOI2019 水站 多种解法

    题目内容 已知有一个\(n\)层的水站: \(W_i\)表示未操作之前第\(i\)层的已有水量: \(L_i\)表示第\(i\)个水站能够维持或者储存的水的重量: 表示在第\(P_i\)层进行减压放水 ...

随机推荐

  1. thinkphp 前置和后置操作

    前置和后置操作指的是在执行某个操作方法之前和之后会自动调用的方法,不过仅对访问控制器有效. 其他的分层控制器层和内部调用控制器的情况下前置和后置操作是无效的. 系统会检测当前操作是否具有前置和后置操作 ...

  2. Vue+Iview+Node 搭建数据模拟接口

    1.初始化node 项目 2.安装需要部件 3.编写简单代码 routers=>:index.js  login.js  users.js 根目录 index.js var express=re ...

  3. UML之类图、时序图、用例图 粗略版介绍

    UML 概述 UML(Unified Modeling Language):统一(标准)建模语言,是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持,包括由需求分析 ...

  4. vue双向绑定的原理

    什么是双向数据绑定?Vue是一个MVVM框架,数据绑定简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化. 实现数据绑定的方式大致有以下几种: - 1.发布者-订阅者 ...

  5. 牛客多校第四场 J Free 最短路

    题意: 求最短路,但是你有k次机会可以把路径中某条边的长度变为0. 题解: 跑k+1次迪杰斯特拉,设想有k+1组dis数组和优先队列,第k组就意味着删去k条边的情况,每次松弛操作,松弛的两点i,j和距 ...

  6. vue打包后index.html界面报错

    vue项目完成后,打包放到服务器上,打开index.html页面时发现一片空白并且报错 很明显是js和css引用不到. 解决办法: 修改vue项目config文件夹下面的index.js,将asset ...

  7. Django杂篇(2)

    目录 Django杂篇(2) cookie与session cookie session django中间件 自定义中间件 跨站请求伪造(csrf) CSRF的解决方案 Django杂篇(2) 本文主 ...

  8. POJ 1127 /// 判断线段与线段是否相交

    题目大意: 给定n条线段 接下来n行是端点信息 接下来询问 a b 是否相交 若a与c相交 b与c相交 ,那么a与b就是相交的 先判断任两条线段是否相交 再用folyd #include <cs ...

  9. USACO 2006 November Gold Corn Fields /// 状压 oj23941

    题目大意: 输入n m 接下来n行m列 0表示不能种玉米 1表示能 要求种玉米位置的上下左右四连通区域不能种玉米 输出方案数 Sample Input 2 31 1 10 1 0 Sample Out ...

  10. selenium基础(控制浏览器)

    python基础(控制浏览器) 控制浏览器 控制浏览器窗口大小 设置浏览器屏幕大小方法:set_window_size() 浏览器最大化:maximize_window() 浏览器最小化:minimi ...