n<=1000,m<=30000的图,问割掉边权和尽量小的0、1或2条边使S和T不连通,输出割了哪些边,无解-1.

道理是很好懂的,先随便找S到T的一条路径,找不到输出0,找到的话这条路上至少有一条边要删,那枚举一下割谁,对剩下的图再做tarjan即可。复杂度(n*m)。

然而!!写起来是很难写的。。

方法一:一开始把所有S到T的路径上的边都标记好,枚举割的第一条边后跑完tarjan,直接看这些边会不会是割边再取min即可。

方法二:枚举割的第一条边后,tarjan求个边双,然后缩起来建树,在树上搜一次。

方法二。

 #include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<vector>
//#include<assert.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n,m,s,t;
#define maxn 1011
#define maxm 60011
struct Edge{int to,v,next;}edge[maxm]; int first[maxn],le=;
void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} int list[maxn],ll=,ans,numofans,whoisans[];
bool vis[maxn];
bool dfs(int x)
{
if (x==t) return ;
vis[x]=;
for (int i=first[x];i;i=edge[i].next)
{
const Edge &e=edge[i]; if (vis[e.to]) continue;
list[++ll]=i>>;
if (dfs(e.to)) return ;
ll--;
}
return ;
} int bel[maxn],tot,Time,low[maxn],dfn[maxn],sta[maxn],top;
struct Tree
{
struct Edge{int to,v,id,next;}edge[maxm]; int first[maxn],le;
void in(int x,int y,int v,int id) {Edge &e=edge[le];e.to=y;e.v=v;e.id=id;e.next=first[x];first[x]=le++;}
void insert(int x,int y,int v,int id) {in(x,y,v,id); in(y,x,v,id);}
bool vis[maxn],ok; int select,selectv;
void clear()
{
memset(vis,,sizeof(vis)); ok=;
memset(first,,sizeof(first)); le=;
}
void dfs(int x,int fa,int Min,int Minid)
{
if (ok) return;
if (x==bel[t])
{
ok=;
if (selectv+Min<ans)
{
ans=selectv+Min;
numofans=;
whoisans[]=select; whoisans[]=Minid;
}
return;
}
vis[x]=;
for (int i=first[x];i && !ok;i=edge[i].next)
{
const Edge &e=edge[i]; if (vis[e.to]) continue;
dfs(e.to,x,min(Min,e.v),e.v<Min?e.id:Minid);
}
}
}T; void tarjan(int x,int f,int who)
{
low[x]=dfn[x]=++Time; sta[++top]=x; vis[x]=;
for (int i=first[x];i;i=edge[i].next)
{
if (i==f || i==(f^) || i==(who<<) || i==((who<<)^)) continue;
const Edge &e=edge[i];
if (!dfn[e.to]) tarjan(e.to,i,who),low[x]=min(low[x],low[e.to]);
else if (vis[e.to]) low[x]=min(low[x],dfn[e.to]);
}
if (low[x]==dfn[x])
{
tot++;
while (sta[top]!=x) bel[sta[top]]=tot,vis[sta[top--]]=;
bel[sta[top--]]=tot,vis[x]=;
}
} void tarjan(int select)
{
top=tot=Time=;
memset(dfn,,sizeof(dfn));
memset(vis,,sizeof(vis));
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i,,select);
if (bel[s]==bel[t]) return;
T.clear();
for (int i=;i<=n;i++)
for (int j=first[i];j;j=edge[j].next) if ((j>>)!=select)
{
const Edge &e=edge[j];
if (bel[i]!=bel[e.to]) T.in(bel[i],bel[e.to],e.v,j>>);
}
T.select=select; T.selectv=edge[select<<].v;
T.dfs(bel[s],,0x7fffffff,);
if (!T.ok) {if (edge[select<<].v<ans) {ans=edge[select<<].v; numofans=; whoisans[]=select;}}
} int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=,x,y,v;i<=m;i++) scanf("%d%d%d",&x,&y,&v),insert(x,y,v);
dfs(s);
if (ll==) {puts("0\n0"); return ;}
numofans=-; ans=0x7fffffff;
for (int i=;i<=ll;i++) tarjan(list[i]);
if (numofans==-) puts("-1");
else
{
printf("%d\n%d\n",ans,numofans);
for (int i=;i<=numofans;i++) printf("%d ",whoisans[i]);
}
return ;
}

Codeforces700C. Break Up的更多相关文章

  1. continue break 区别

    在循环中有两种循环方式 continue , break continue 只是跳出本次循环, 不在继续往下走, 还是开始下一次循环 break  将会跳出整个循环, 此循环将会被终止 count = ...

  2. C# 中Switch case 返回不止用break

    Switch(temp) { case "A": //跳出循环 break; case "B": //返回值 return var; case "C& ...

  3. jquery each函数 break和continue功能

    jquery each函数 break和continue功能幸运的是另一个突破,持续一个jQuery循环方式.你可以打破在函数返回一个jQuery参数虚假循环.一个可以继续执行只是在做不指定返回值或返 ...

  4. [LeetCode] Integer Break 整数拆分

    Given a positive integer n, break it into the sum of at least two positive integers and maximize the ...

  5. [LeetCode] Word Break II 拆分词句之二

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  6. R for循环之break,next

    next跳出本次循环 break跳出本层循环(当有多个for 循环时,即跳出最近的一个for循环)

  7. 关于break语句如何结束多重循环的嵌套

    在Java中的break语句功能大体上同c语言, 用于循环语句中,表示结束当前循环. 但是有时候在循环嵌套语句中,仅仅靠一 个break语句想实现是不够的. 例: 如果想使sum在501时就直接输出, ...

  8. break与continue的区别

    break       在while.for.do...while.while循环中使用break语句退出当前循环,直接执行后面的代码. continue   的作用是仅仅跳过本次循环,而整个循环体继 ...

  9. 高程(3):操作符、for、for...in循环、break/continue/return语句、函数等

    1.关系操作符 注意点:1)比较操作数是两个字符串,是比较字符串的字符编码值. 如:"a" > "b"  返回 false:"a" & ...

随机推荐

  1. jquery判断checkbox最多选几个

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  2. php安装ionCube

  3. javascript中函数的四种调用模式详解

    介绍函数四种调用模式前,我们先来了解一下函数和方法的概念,其实函数和方法本质是一样,就是称呼不一样而已.函数:如果一个函数与任何对象关系,就称该函数为函数.方法:如果一个函数作为一个对象属性存在,我们 ...

  4. ES6学习笔记(1)----let和const命令

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ let和const命令 let 总结1.声明变量基本使用方法与var 相同  不同点  a.在代 ...

  5. Prim算法以及Kruskal算法

    Prim算法主要用于计算最小生成树.算法在选取最小路径的时候需要优化,算法思路:从某个顶点开始,假设v0,此时v0属于最小生成树结点中的一个元素,该集合假设V,剩下的点待选择的点为U,然后找寻V中的点 ...

  6. 5 Transforms 转移 笔记

    5 Transforms 转移 笔记   Transforms    Unfortunately, no one can be told what the Matrix is. You have to ...

  7. MySQL学习随笔--视图

    视图概念 数据库中的视图指的是一个虚拟表,其内容由查询定义.同真实的表一样,视图也是由行与列构成的.视图的数据来源由SQL语句查询得到,不存储数据 视图创建方法 格式 : create view 视图 ...

  8. 手动配置wamp环境(1)--apache安装与基本操作

    Apache服务器简介: Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一. 安装apac ...

  9. ansys中的.full文件中如何看刚度矩阵和质量矩阵(转)

    http://fffff-2001.blog.163.com/blog/static/15507529200722492917460 Q:请问ansys中的.full文件中如何看刚度矩阵和质量矩阵? ...

  10. iTOP-6818开发板-Android4.4系统下RFID射频模块测试例程

    平台:迅为iTOP-6818开发板 系统:Android4.4版本 例程:RFID射频模块测试例程 rc522 驱动在 Android 系统的内核是默认集成的,用户可以在开发板上使用命令“ls /de ...