CF700C (枚举+tarjan)
Problem Break up (CF700C)
题目大意
给一张n个点,m条边的无向图,有边权,和起点S,终点T。 (n<=1000 , m<=30000)
要求最多割掉2条边,使得S到T不连通。
输出最小代价以及方案。
解题分析
如果只是割掉1条边,那么就是求割边了。
如果要割掉2条边,一个自然的思路就是枚举一条边后再求割点,这样复杂度是O(m ^2)的,显然会超时。
再考虑并不需要枚举每一条边,只需要求一条S到T的路径,枚举这条路径上的边即可。因为若要不连通,必定要割掉这条路径上的某一条边
复杂度O(n*m)。
参考程序
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std; #define N 100008
#define V 1008
#define E 60008
#define lson l,m,rt<<1
#define rson m,r+1,rt<<1|1
#define clr(x,v) memset(x,v,sizeof(x));
#define LL long long const int mo = ;
const int inf = 0x3f3f3f3f;
const int INF = ;
/**************************************************************************/ int n,m,S,T,tmp;
int vis[V],path[V],dfn[V],low[V],road[V],bridge[E];
int ans;
int ANS[V];
struct line{
int u,v,w,nt;
}eg[E];
int sum,lt[V]; void adt(int u,int v,int w){
eg[++sum]=(line){u,v,w,lt[u]};
lt[u]=sum;
}
void add(int u,int v,int w){
adt(u,v,w); adt(v,u,w);
} bool dfs(int u){
vis[u]=;
if (u==T) return true;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (vis[v]) continue;
if (dfs(v)){
path[++path[]]=i/;
return true;
}
}
return false;
} bool dfs_2(int u,int del){
vis[u]=;
if (u==T) return true;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (i/==del) continue;
if (vis[v]) continue;
if (dfs_2(v,del)){
road[++road[]]=i/;
return true;
}
}
return false;
}
void tarjan(int u,int fa,int del){
dfn[u]=low[u]=++tmp;
int flag=;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (i/==del) continue;
if (v==fa && !flag){
flag=;
continue;
}
if (!dfn[v]){
tarjan(v,u,del);
low[u]=min(low[u],low[v]);
if (dfn[u]<low[v]) bridge[i/]=;
}
else low[u]=min(low[u],dfn[v]);
}
} int main(){
scanf("%d %d",&n,&m);
scanf("%d %d",&S,&T);
sum=;
for (int i=;i<=m;i++){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
} clr(vis,);
clr(path,);
if (!dfs(S)) { printf("0\n0\n"); return ; }
else
{
ans=INF;
for (int ii=;ii<=path[];ii++){
clr(bridge,);
clr(vis,);
clr(road,);
clr(dfn,);
tmp=;
for (int i=;i<=n;i++)
if (!dfn[i])
tarjan(i,,path[ii]);
if (!dfs_2(S,path[ii])){
if (eg[path[ii]*].w<ans){
ans = eg[path[ii]*].w;
ANS[]=;
ANS[]=path[ii];
}
}
else
{
for (int i=;i<=road[];i++){
if (bridge[road[i]]){
if (eg[road[i]*].w+eg[path[ii]*].w<ans){
ans=eg[road[i]*].w+eg[path[ii]*].w;
ANS[]=;
ANS[]=road[i];
ANS[]=path[ii];
}
}
}
}
}
if (ans==INF) printf("-1\n");
else
{
printf("%d\n%d\n",ans,ANS[]);
for (int i=;i<=ANS[];i++) printf("%d%c",ANS[i],i!=ANS[]?' ':'\n');
}
}
}
CF700C (枚举+tarjan)的更多相关文章
- poj3713 Transferring Sylla 枚举+tarjan判割点
其实就是判断是否为三连通图 三连通图指的是去掉3个点就不连通的图,但是并没有直接求三连通的算法.著名的Tarjan算法可以求解连通和割点,再枚举删除一个点就能达到三连通的目的. 先看用例2,是由用例1 ...
- 有向图强连通分量的Tarjan算法
有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...
- [学习笔记]tarjan求割点
都口胡了求割边,就顺便口胡求割点好了QAQ 的定义同求有向图强连通分量. 枚举当前点的所有邻接点: 1.如果某个邻接点未被访问过,则访问,并在回溯后更新 2.如果某个邻接点已被访问过,则更新 对于当前 ...
- [学习笔记]tarjan求割边
上午打模拟赛的时候想出了第三题题解,可是我不会求割边只能暴力判割边了QAQ 所以,本文介绍求割边(又称桥). 的定义同求有向图强连通分量. 枚举当前点的所有邻接点: 1.如果某个邻接点未被访问过,则访 ...
- 【BZOJ-1179】Atm Tarjan + SPFA
1179: [Apio2009]Atm Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 2407 Solved: 993[Submit][Status ...
- 强连通分量的Tarjan算法
资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...
- code vs1506传话(塔尖)+tarjan图文详解
1506 传话 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 题目描述 Description 一个朋友网络,如果a认识b,那么如果a第一次收到 ...
- [知识点]Tarjan算法
// 此博文为迁移而来,写于2015年4月14日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vxnx.html UPD ...
- 【Tarjan】+【SPFA】APIO2009 Atm
一.算法介绍 tarjan——求解有向图强连通分量.这个算法在本人的一篇blog中有介绍,这里就不赘述了.贴上介绍tarjan的的blog链接:http://www.cnblogs.com/Maki- ...
随机推荐
- Redis(7)Creating and Using Cluster Mode
1. DocumentsCluster will not support SELECT, it only contains database 0.All the nodes use TCP bus a ...
- 20145236 《Java程序设计》课程总结
20145236 <Java程序设计>课程总结 一.每周读书笔记链接汇总 第一周读书笔记 第二周读书笔记 第三周读书笔记 第四周读书笔记 第五周读书笔记 第六周读书笔记 第七周读书笔记 第 ...
- C#获取相对路径的方法
这八种C#获取相对路径的方法,包括获取和设置当前目录的完全限定路径.获取启动了应用程序的可执行文件的路径,不包括可执行文件的名称等等内容. C#获取相对路径1. 获取和设置当前目录的完全限定路径. ...
- Go语言并发与并行学习笔记(二)
转:http://blog.csdn.net/kjfcpua/article/details/18265461 Go语言的并发和并行 不知道你有没有注意到一个现象,还是这段代码,如果我跑在两个goro ...
- [整理]Linux压缩与解压缩命令整理。
一.压缩文件命令 1.*.Z compress 程序压缩的档案:2.*.bz2 bzip2 程序压缩的档案:3.*.gz gzip 程序压缩的档案:4.*.tar tar 程序打包的数据,并没有压缩过 ...
- RHEL 5 安装phpqrcode生成二维码
VMWARE中全新安装(默认)RHEL. 之后,yum 安装备apache/php 下载并上传phpqrcode 1.1.4版本,并将其解压至/var/www/html/phpqrcode (去掉ip ...
- java反射之Class.getMethod与getDeclaredMethods()区别
Class对象的getMethods和getDeclaredMethods都是获取类对象的方法.但是又有所不同.废话不多说, 先看demo package com.westward; public c ...
- Js笔试题之parseInt()和.map()
parseInt()的几个例子 var b = parseInt("01"); alert("b="+b); var c = parseInt("09 ...
- js正则表达式和replace
javascript中replace与正则表达式 replace()最简单的算是能力就是简单的字符替换.示例代码如下: <script language="javascript&quo ...
- 转: Oracle中的物化视图
物化视图创建语法:CREATE MATERIALIZED VIEW <schema.name>PCTFREE <integer>--存储参数PCTUSED <intege ...