FJ省队集训DAY3 T2



思路:如果一个DAG要的路径上只要一条边去切掉,那么要怎么求?很容易就想到最小割,但是如果直接做最小割会走出重复的部分,那我们就这样:反向边设为inf,这样最小割的时候就不会割到了,判断无解我们直接用tarjan
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
const ll inf = 1ll << ;
struct edge{
int u,v,w;
}e[];
ll flow[];
int op[],dis[],cnt[],a[][],pd[];
int tot,go[],next[],first[],S,T,nodes,sz;
int n,m,vis[],instack[],c[],top,dfn[],low[],belong[],num;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-')f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void insert(int x,int y,ll z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
flow[tot]=z;
}
void add(int x,int y,ll z){
insert(x,y,z);op[tot]=tot-;
insert(y,x,inf);op[tot]=tot+;
}
void tarjan(int x){
vis[x]=instack[x]=;
c[++top]=x;dfn[x]=low[x]=++sz;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (!vis[pur]){
tarjan(pur);
low[x]=std::min(low[x],low[pur]);
}else if (instack[pur]){
low[x]=std::min(low[x],dfn[pur]);
}
}
if (low[x]==dfn[x]){
num++;
while (c[top]!=x){
belong[c[top]]=num;
instack[c[top]]=;
top--;
}
belong[c[top]]=num;
instack[c[top]]=;
top--;
}
}
ll dfs(int x,ll f){
if (x==T) return f;
int mn=nodes;ll sum=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (flow[i]&&dis[pur]+==dis[x]){
ll F=std::min(f-sum,flow[i]);
ll save=dfs(pur,F);
flow[i]-=save;
flow[op[i]]+=save;
sum+=save;
if (dis[S]>=nodes||f==sum) return sum;
}
if (flow[i]) mn=std::min(mn,dis[pur]);
}
if (sum==){
cnt[dis[x]]--;
if (cnt[dis[x]]==){
dis[S]=nodes;
}else{
dis[x]=mn+;
cnt[dis[x]]++;
}
}
return sum;
}
int main(){
n=read();m=read();
for (int i=;i<=m;i++){
e[i].u=read()+,e[i].v=read()+,e[i].w=read();
a[e[i].u][e[i].v]=;
insert(e[i].u,e[i].v);
}
for (int i=;i<=n;i++)
if (!vis[i]) tarjan(i);
if (belong[]==belong[n]){
puts("-1");
return ;
}
for (int i=;i<=n;i++)
a[i][i]=;
for (int k=;k<=n;k++)
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
a[i][j]|=a[i][k]&&a[k][j];
for (int i=;i<=n;i++)
if (a[][i]&&a[i][n]) pd[i]=;
for (int i=;i<=m;i++)
if (pd[e[i].u]&&pd[e[i].v])
add(e[i].u,e[i].v,e[i].w);
S=;T=n;nodes=n;
int ans=;
while (dis[S]<nodes&&ans<inf) ans+=dfs(S,inf);
if (ans==) printf("-1");
else printf("%d\n",ans);
}
FJ省队集训DAY3 T2的更多相关文章
- FJ省队集训DAY3 T1
思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分. 因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的 ...
- FJ省队集训DAY4 T2
XXX #include<cstdio> #include<iostream> #include<cmath> #include<cstring> #i ...
- FJ省队集训DAY2 T2
思路:我们可以考虑三角剖分,这样问题就变成考虑三角形的选取概率和三角形内有多少个点了. 先用树状数组预处理出三角剖分的三角形中有多少个点,然后用线段树维护,先用原点极角排序,然后枚举i,再以i极角排序 ...
- FJ省队集训最终测试 T2
思路:发现如果一个人一共选了x个点,那么选中某一个点对的概率都是一样的,一个人选x个点的总方案是C(n,x),一个人选中某个点对的总方案是C(n-2,x-2),这样,那么选中某个点对的概率就是 x*( ...
- FJ省队集训DAY2 T1
思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可 ...
- FJ省队集训DAY1 T1
题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会 ...
- 省队集训Day3 light
[问题描述] “若是万一琪露诺(俗称 rhl)进行攻击,什么都好,冷静地回答她的问题来吸引她.对方表现出兴趣的话,那就慢慢地反问.在她考虑答案的时候,趁机逃吧.就算是很简单的问题,她一定也答不上来.” ...
- 省队集训Day3 tree
[题目描述] RHL 有一天看到 lmc 在玩一个游戏. “愚蠢的人类哟,what are you doing”,RHL 说. “我在玩一个游戏.现在这里有一个有 n 个结点的有根树,其中有 m 个叶 ...
- bzoj4171 or 省队集训day3 chess: Rhl的游戏
[题目描述] RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色.每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少 ...
随机推荐
- iOS 9之应用内搜索(CoreSpotlight)API
金田(github 示例源码) 前言 在iOS9之前我们只能使用Spotlight来搜索应用名称来打开指定App,而其他的内容都是提供给系统使用(信息,联系人,邮件等).在iOS9以后Apple允许开 ...
- 黑马程序员_Java集合框架
集合类 1,为什么出现集合类? 面向对象语言对食物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 2,数组和集合类同是容器,有何不同? 数组 ...
- cf435A Queue on Bus Stop
A. Queue on Bus Stop time limit per test 1 second memory limit per test 256 megabytes input standa ...
- 小记UNIX编程库调用.
更好的文章:http://www.cppblog.com/deane/articles/165216.html 静态库生成:(举例加法库) 1.编程源程序 add.h add.c 2.编译源程序,生成 ...
- SRM 585 DIV1
A 树形dp是看起来比较靠谱的做法 , 但是转移的时候不全面就会出错 , 从贪心的角度出发 , 首先让第一量车走最长路, 然后就会发现递归结构 , 得到递归式 f[i] = ( f[i-2] + f[ ...
- 并发队列之:BlockingQueue和ConcurrentLinkedQueue
一.并行和并发区别: 并行:是指两者同时执行一件事.比如赛跑,两个人都在不停的往前跑: 并发:是指资源有限的情况下,两者交替轮流使用资源.比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给 ...
- jq指定行切换
function G(){ var item=$('.req_list_item>li'); item.find($('.req_show')).hover(function(){ $(this ...
- checkbox 与JS的应用
JS是一种基于(面向)对象的语言.所有的东西都基本上是对象. 基于对象和面向对象概念上基本上没有什么区别. js没有类,它把类功能称为原型对象.是同一个概念.主要是因为js没有class关键字.类== ...
- Android邮件发送详解
转载:http://flysnow.iteye.com/blog/1128354 Android中我为什么发不了邮件???我手机里明明有邮件客户端的,可我为什么不能调用它发送邮件???相信这是很多人会 ...
- RPM包查询
一.查询包是否安装 [root@localhost Packages]# rpm -q httpd ---> 查询已安装的包(命令包名) #选项: # -q 查 ...