Codeforces700C. Break Up
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的更多相关文章
- continue break 区别
在循环中有两种循环方式 continue , break continue 只是跳出本次循环, 不在继续往下走, 还是开始下一次循环 break 将会跳出整个循环, 此循环将会被终止 count = ...
- C# 中Switch case 返回不止用break
Switch(temp) { case "A": //跳出循环 break; case "B": //返回值 return var; case "C& ...
- jquery each函数 break和continue功能
jquery each函数 break和continue功能幸运的是另一个突破,持续一个jQuery循环方式.你可以打破在函数返回一个jQuery参数虚假循环.一个可以继续执行只是在做不指定返回值或返 ...
- [LeetCode] Integer Break 整数拆分
Given a positive integer n, break it into the sum of at least two positive integers and maximize the ...
- [LeetCode] Word Break II 拆分词句之二
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...
- R for循环之break,next
next跳出本次循环 break跳出本层循环(当有多个for 循环时,即跳出最近的一个for循环)
- 关于break语句如何结束多重循环的嵌套
在Java中的break语句功能大体上同c语言, 用于循环语句中,表示结束当前循环. 但是有时候在循环嵌套语句中,仅仅靠一 个break语句想实现是不够的. 例: 如果想使sum在501时就直接输出, ...
- break与continue的区别
break 在while.for.do...while.while循环中使用break语句退出当前循环,直接执行后面的代码. continue 的作用是仅仅跳过本次循环,而整个循环体继 ...
- 高程(3):操作符、for、for...in循环、break/continue/return语句、函数等
1.关系操作符 注意点:1)比较操作数是两个字符串,是比较字符串的字符编码值. 如:"a" > "b" 返回 false:"a" & ...
随机推荐
- DEV—【GridControl 按钮列无法触发点击事件解决方案】
需要在按钮列的OptionColumn属性栏中找到下面两个属性,并且改为True AllowEdit=True,AllowFocus=True.
- 手写一套迷你版HTTP服务器
本文主要介绍如何通过netty来手写一套简单版的HTTP服务器,同时将关于netty的许多细小知识点进行了串联,用于巩固和提升对于netty框架的掌握程度. 服务器运行效果 服务器支持对静态文件css ...
- [SPOJ1812]Longest Common Substring II 后缀自动机 多个串的最长公共子串
题目链接:http://www.spoj.com/problems/LCS2/ 其实两个串的LCS会了,多个串的LCS也就差不多了. 我们先用一个串建立后缀自动机,然后其它的串在上面跑.跑的时候算出每 ...
- P1118 [USACO06FEB]数字三角形Backward Digit Su…
题目描述 FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N ...
- 用pycharm+django开发web项目
pycharm是python的一个商业的集成开发工具,本人感觉做python开发还是很好用的,django是一个很流行的python web开源框架,本文就是使用pycharm+django来开发py ...
- javaEE web 系统安装时自定义初始化
通常JavaWeb项目在第一次启动时我们需要做一些初始化工作,比如:初始化一个管理员的登录账户和密码,配置缓存.定时任务等,这些操作可以通过手工修改数据库完成,但是容易出错且繁琐,而且也很麻烦.如果这 ...
- 使用Jenkins进行android项目的自动构建(4)
加入单元测试 android单元测试很多都是使用Instrumentation进行的,这里讲的是试用JUnit,为什么用JUnit呢?因为使用Instrumentation需要打包apk安装,然后再进 ...
- Farseer.net轻量级ORM开源框架说明及链接索引
项目简介 基于.net framework 4 开发. 基于Lambda表达式快速上手的ORM框架. 参考Entity Framework的调用方式. 基于Database First模式. POCO ...
- Mac eclipse java6环境安装
由于旧版adtbundle eclipse需要java se6版本支持,而较新版本mac系统默认安装较高的java版本,所以这里需要卸载高版本jdk(1.8),然后安装1.6 mac删除jdk jav ...
- python学习(day2)
1.常用数据类型及内置方法 1.列表(list) 定义:在中括号[]内存放任意多个值,用逗号隔开. 具体函数和内置方法如下: #定义学生列表,可存放多个学生 students=['a','b','c' ...