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)选文收益, ...
随机推荐
- .net 未被引用的错误
开发的时候遇到了一个错误,如下: 错误 1 类型“System.ServiceModel.ClientBase`1<T0>”在未被引用的程序集中定义. 我原本以为是版本号的问题,添加了引用 ...
- element-ui合并行:span-method
objectSpanMethod({ row, column, rowIndex, columnIndex }) { if (columnIndex === 0) { if (rowIndex % 2 ...
- nginx配置自动跳转
阅读更多 希望实现的效果是,用户只要访问域名,自动跳转到index.html页面 原本配置为: location / { root /users/apple/git_local/YAE/YAE/f ...
- UVALive - 4094 WonderTeam (贪心)
题目大意: 有n支队伍,每两支队伍打两场比赛(主客场各一次),胜得3分,平得1分,输不得分,比赛结束之后会评选出一个梦之队,梦之队满足以下条件:进球总数最多,胜利场数最多,丢求总数最少,三个都不能并列 ...
- 20155230 2016-2017-2 《Java程序设计》第五周学习总结
20155230 2016-2017-2 <Java程序设计>第五周学习总结 教材学习内容总结 1.错误处理通常称为异常处理. 2.catch括号中列出的异常不得有继承关系,否则会发生编译 ...
- 【项目部署】部署项目以war包部署和解开以目录部署的区别
我们都知道最简单的部署web项目的方式是打成war包直接仍在tomcat的webapps目录下,我上个项目也确实是这样做的,可是这给我们后期的维护带来了极大的不便,下面就简单研究一下以war包部署和解 ...
- Java练习之使用StringBuilder
package string.demo; /* * 将数组变为字符串输出 */ public class StringBuilderTest { /** * @param args */ public ...
- python3之memcached
1.memcached介绍 Memcached是一个自由开源的,高性能,分布式内存对象缓存系统. Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fi ...
- nagios报警延迟的解决--flapping state
这个问题是在测试中发现的.因为要在服务器上布置nagios用来监控oracle,可是发现手动shutdown数据库后能够很快报警,但是再startup后就不是很及时,有时会延迟很久.经过研究发现了这个 ...
- WPF使用DataGridComboBoxColumn完成绑定
在使用DataGrid的时候,有时候需要使某些列为ComboBox,这时自然想到使用DataGridComboBoxColumn,但是如果使用的是ItemsSource数据绑定后台的对象,就会发现,这 ...