CF700C Break Up
时间:2021-09-06
本文章向大家介绍CF700C Break Up,主要包括CF700C Break Up使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
statement
给你一个 \(n\) 个点 \(m\) 条边的无向图,边有权值,要求你删去最多两条边,使得 \(s\) 与 \(t\) 不连通,且删去的边权值和最小。
Hints
\(2\le n\le 1000\) ,\(0\le m \le 30000\)
solution
首先考虑删除一条边的情况,必定是有一条从 \(s\) 到 \(t\) 的所有路径中,都经过的一条边,随便找一条路径枚举即可,时间复杂度 \(\mathcal O (n\times m)\) 。
两条路径的情况就是把一条边删去后,又出现了一条如上述的边,而直接枚举两条边的复杂度是 \(\mathcal O (m ^ 3)\) 的,通过 tarjan
算法判桥可以做到 \(\mathcal O (m ^ 2)\) 。
很容易发现,这样枚举是有完全不可能合法的方案的,运用人类智慧,发现在同一条 \(s\rightarrow t\) 的路径上必定有一条边是会被删去的。
所以直接先拉出任意一条路径,直接暴力枚举即可,时间复杂度 \(\mathcal O (n\times m)\) 。
struct Lst {
int dir, nxt, w;
Lst() {}
Lst(int _d, int _n, int _w) : dir(_d), nxt(_n), w(_w) {}
} E[M << 1];
int G[N], cnt = 1;
inline void Add(int u, int v, int w) {E[++cnt] = Lst(v, G[u], w), G[u] = cnt;}
int n, m, s, t, ban, dfn[N], ord, brg[M], vis[M], vt[M], lst[N], res = 2e9 + 1;
vector<int> pth;
void path(int u) {
vis[u] = 1; if(u == t) return ;
for(register int i=G[u], v; i; i=E[i].nxt) if(i != ban && i != (ban ^ 1)) {
v = E[i].dir;
if(vis[v]) continue ;
lst[v] = i, path(v);
}
}
int tarjan(int u) {
int low = dfn[u] = ++ord, lowv;
for(register int i=G[u], v; i; i=E[i].nxt) if(!vt[i]) {
v = E[i].dir, vt[i] = vt[i ^ 1] = 1;
if(!dfn[v]) {
low = min(low, lowv = tarjan(v));
if(lowv > dfn[u]) {
brg[i >> 1] = 1;
}
} else if(dfn[v] < dfn[u]) low = min(low, dfn[v]);
}
return low;
}
int ansl, ansr;
int main() {
scanf("%d%d%d%d", &n, &m, &s, &t);
forn(i,1,m) {
static int u, v, w;
scanf("%d%d%d", &u, &v, &w);
Add(u, v, w), Add(v, u, w);
}
ban = 1e9, path(s);
if(!vis[t]) return printf("0\n0\n") & 0;
int tmp = t;
while(tmp != s) pth.push_back(lst[tmp]), tmp = E[lst[tmp] ^ 1].dir;
ansl = ansr = -1;
rep(i,0,pth.size()) {
ban = pth[i], ord = 0;
memset(dfn, 0, sizeof dfn);
memset(brg, 0, sizeof brg);
memset(vis, 0, sizeof vis);
memset(lst, 0, sizeof lst);
memset(vt, 0, sizeof vt);
vt[pth[i]] = vt[pth[i] ^ 1] = 1;
path(s);
if(!vis[t]) {
if(res > E[pth[i]].w) res = E[pth[i]].w, ansl = pth[i], ansr = -1;
} else {
tarjan(s), tmp = t;
while(tmp != s) {
int e = lst[tmp];
if(brg[e >> 1]) if(res > E[pth[i]].w + E[e].w)
res = E[pth[i]].w + E[e].w, ansl = pth[i], ansr = e;
tmp = E[e ^ 1].dir;
}
}
}
if(res == 2e9 + 1) return puts("-1") & 0;
if(ansr == -1) {
printf("%d\n1\n", res);
printf("%d\n", ansl >> 1);
} else {
printf("%d\n2\n", res);
printf("%d %d\n", ansl >> 1, ansr >> 1);
}
return 0;
}
原文地址:https://www.cnblogs.com/Ax-Dea/p/15234148.html
- Spring Boot 中使用 MongoDB 增删改查
- 来人啊给我炸了那个Java虚拟机No.46
- 机器学习虾扯淡之Logistic回归No.44
- 大数据计数原理1+0=1这你都不会算(一)No.47
- 机器学习虾扯蛋之SVD奇异值分解No.48
- 提高Spark姿势水平 No.73
- 好好玩的螺旋算法No.69
- linux学习第四十篇:访问日志不记录静态文件,访问日志切割,静态元素过期时间
- linux学习第四十一篇:配置防盗链,访问控制Directory,访问控制FilesMatch
- linux学习第四十二篇:限定某个目录禁止解析php, 限制user_agent,PHP相关配置
- 简易但不简单的配置中心No.79
- linux学习第四十三篇:LNMP架构介绍,mysql安装,php安装,Nginx介绍
- linux学习第四十四篇:Nginx安装,Nginx默认虚拟主机,Nginx域名重定向
- linux学习第四十二篇:PHP扩展模块安装
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MATLAB 与 C 语言的混合编程实战之辛普森积分法、自适应辛普森积分
- Java那些事之JDK环境配置及集成开发环境Eclipse安装
- 敲代码、作诗、写论文无所不能?史上最大AI模型GPT-3霸榜Github
- 数据结构实验——校园导游 实现最小生成树+最短路
- Salesforce LWC学习(二十六) 简单知识总结篇三
- 【Java】13 异常
- 【Java】14 多线程
- 【Java】16 字节流
- 【Java】17 字符流
- 极坐标系在数据可视化中的巧妙运用
- 【Java】18 增强流
- 【Java】19 网络编程
- 【Java】20 基于 TCP 协议的网络编程
- 【Java】01 初识 Java
- 多张热图的排版技巧