BZOJ.2521.[SHOI2010]最小生成树(最小割ISAP/Dinic)
一条边不变其它边减少可以看做一条边增加其它边不变。
假设要加的边lab为(A->B,v),那么肯定是要使除这条边外,A->B的每条路径上的最小权值都\(>v\),这样在连通A,B时(即Kruskal中Union())才一定会选择这条边。
要求路径上最小边的权值\(>v\),即要求在路径上有任意一边权值\(\leq v\)时不连通。于是求最小割(使它不连通),割掉一条边的代价即\(v[lab]-v[i]+1\)。
无向图建双向边。
status里的怎么都那么快?复制了一份20的也60+
ISAP:
//892kb 64ms
//ISAP lev[]的上限是n不是des。。
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=505,M=3215;
int n,m,lab,s[805],t[805],v[805];
int src,des,Enum,cur[N],H[N],nxt[M],fr[M],to[M],cap[M],pre[N],lev[N],que[N],num[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int w)
{
to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w;
to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0;
}
bool BFS()
{
for(int i=1; i<=n; ++i) lev[i]=n+1;
lev[des]=0, que[0]=des; int h=0,t=1;
while(h<t)
{
int x=que[h++];
for(int i=H[x]; i; i=nxt[i])
if(lev[to[i]]==n+1 && cap[i^1])
lev[to[i]]=lev[x]+1, que[t++]=to[i];
}
return lev[src]<=n;
}
int Augment()
{
int mn=1e9;
for(int i=des; i!=src; i=fr[pre[i]])
mn=std::min(mn,cap[pre[i]]);
for(int i=des; i!=src; i=fr[pre[i]])
cap[pre[i]]-=mn, cap[pre[i]^1]+=mn;
return mn;
}
int ISAP()
{
if(!BFS()) return 0;
for(int i=1; i<=n; ++i) ++num[lev[i]],cur[i]=H[i];
int x=src,res=0;
while(lev[src]<=n)
{
if(x==des) x=src,res+=Augment();
bool can=0;
for(int i=cur[x]; i; i=nxt[i])
if(lev[to[i]]==lev[x]-1 && cap[i])
{
can=1, cur[x]=i, pre[x=to[i]]=i;
break;
}
if(!can)
{
int mn=n;
for(int i=H[x]; i; i=nxt[i])
if(cap[i]) mn=std::min(mn,lev[to[i]]);
if(!--num[lev[x]]) break;
++num[lev[x]=mn+1], cur[x]=H[x];
if(x!=src) x=fr[pre[x]];
}
}
return res;
}
int main()
{
n=read(),m=read(),lab=read(),Enum=1;
for(int i=1; i<=m; ++i) s[i]=read(),t[i]=read(),v[i]=read();
src=s[lab], des=t[lab];
for(int i=1; i<=m; ++i)
if(i!=lab&&v[i]<=v[lab]) AddEdge(s[i],t[i],v[lab]-v[i]+1),AddEdge(t[i],s[i],v[lab]-v[i]+1);
printf("%d",ISAP());
return 0;
}
Dinic:
//876kb 60ms 果然差不多
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=505,M=3215;
int n,m,lab,s[805],t[805],v[805];
int src,des,Enum,cur[N],H[N],nxt[M],to[M],cap[M],lev[N],que[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int w)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0;
}
bool BFS()
{
for(int i=1; i<=n; ++i) lev[i]=0,cur[i]=H[i];
lev[src]=1, que[0]=src; int h=0,t=1;
while(h<t)
{
int x=que[h++];
for(int i=H[x]; i; i=nxt[i])
if(!lev[to[i]] && cap[i])
{
lev[to[i]]=lev[x]+1, que[t++]=to[i];
if(to[i]==des) return 1;
}
}
return 0;
}
int Dinic(int x,int flow)
{
if(x==des) return flow;
int used(0);
for(int &i=cur[x]; i; i=nxt[i])
if(lev[to[i]]==lev[x]+1&&cap[i])
{
int delta=Dinic(to[i],std::min(flow-used,cap[i]));
if(delta)
{
cap[i]-=delta, cap[i^1]+=delta;
if((used+=delta)==flow) return flow;
}
}
lev[x]=0;
return used;
}
int main()
{
n=read(),m=read(),lab=read(),Enum=1;
for(int i=1; i<=m; ++i) s[i]=read(),t[i]=read(),v[i]=read();
src=s[lab], des=t[lab];
for(int i=1; i<=m; ++i)
if(i!=lab&&v[i]<=v[lab]) AddEdge(s[i],t[i],v[lab]-v[i]+1),AddEdge(t[i],s[i],v[lab]-v[i]+1);
int res=0;
while(BFS()) res+=Dinic(src,1e9);
printf("%d",res);
return 0;
}
BZOJ.2521.[SHOI2010]最小生成树(最小割ISAP/Dinic)的更多相关文章
- BZOJ 2521: [Shoi2010]最小生成树
2521: [Shoi2010]最小生成树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 445 Solved: 262[Submit][Statu ...
- BZOJ 2521: [Shoi2010]最小生成树(最小割)
题意 对于某一条无向图中的指定边 \((a, b)\) , 求出至少需要多少次操作.可以保证 \((a, b)\) 边在这个无向图的最小生成树中. 一次操作指: 先选择一条图中的边 \((u, v)\ ...
- BZOJ2521:[SHOI2010]最小生成树(最小割)
Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可 ...
- BZOJ2521[Shoi2010]最小生成树——最小割
题目描述 Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可能有多种不同的 ...
- BZOJ.3532.[SDOI2014]LIS(最小割ISAP 退流)
BZOJ 洛谷 \(LIS\)..经典模型? 令\(f_i\)表示以\(i\)结尾的\(LIS\)长度. 如果\(f_i=1\),连边\((S,i,INF)\):如果\(f_i=\max\limits ...
- 【BZOJ2521】[Shoi2010]最小生成树 最小割
[BZOJ2521][Shoi2010]最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算 ...
- 【BZOJ-2521】最小生成树 最小割
2521: [Shoi2010]最小生成树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 415 Solved: 242[Submit][Statu ...
- BZOJ 2561: 最小生成树(最小割)
U,V能在最小(大)生成树上,当且仅当权值比它小(大)的边无法连通U,V. 两次最小割就OK了. --------------------------------------------------- ...
- bzoj 2127 happiness【最小割+dinic】
参考:https://www.cnblogs.com/chenyushuo/p/5144957.html 不得不说这个建图方法真是非常妙啊 假设S点选理,T点选文,a[i][j]为(i,j)选文收益, ...
随机推荐
- javaweb购物车实现的几种方式
之前没有接触过购物车的东东,也不知道购物车应该怎么做,所以在查询了很多资料,总结一下购物车的功能实现. 查询的资料,找到三种方法: 1.用cookie实现购物车: 2.用session实现购物车: 3 ...
- 【1】ConcurrentModificationException 异常解析和快速失败,安全失败
目录 一.引起异常的代码 二.foreach原理 三.从ArrayList源码找原因 四.单线程解决方案 五.在多线程环境下的解决方法 一.引起异常的代码 以下三种的遍历集合对象时候,执行集合的rem ...
- Mybatis 使用 mapper 接口规范的 一对一, 一对多,多对多映射
首先的 是 最原始的 pojo 类来 做简单映射 简单 pojo 映射: <mapper namespace="com.ghc.dao.UserDao"> <se ...
- SCI写作经典替换词
- 重启sqlserver服务 命令
在控制台(CMD)中运行: net stop mssqlserver net start mssqlserver
- python scrapy cookies 处理
def start_requests(self): cookies = 'anonymid=jcokuqwe................省略' # 首先是对cookies进行分割以;为节点 ook ...
- Redis知识点总结
1.单线程 单线程模型来处理客户端的请求,对读写等事件的相应是通过对epoll函数的包装来做到的,Redis的实际处理速度完全依靠主线程的执行效率. Epoll是Linux内核为处理大批量文件描述符而 ...
- orm 缺点
背景 提起orm,在我开发这几年可是阴魂不散,因为我的开发没人带,全是自己琢磨,好处是很多东西都懂,都理解的透彻,缺点是见得少,接触少.而我一直没用orm,但是又到处听说orm,但我总想不明白有啥用处 ...
- Pandas DataFrame数据的增、删、改、查
Pandas DataFrame数据的增.删.改.查 https://blog.csdn.net/zhangchuang601/article/details/79583551 #删除列 df_2 = ...
- spring-mvc集成 swagger
问题1:spring-mvc集成 swagger, 配置好后界面 404, 原因: dispatcher-servlet.xml 文件中, 要在这上面 <!-- 启用spring mvc 注解 ...