hdu2435最大流最小割
2014-03-22 我来说两句 来源:hdu2435最大流最小割 收藏 我要投稿
2435 There is a war 题意:
给你一个有向图,其中可以有一条边是无敌的,这条边可以是图中的边,也可以是自己任意加上去的图中没有的边,这条无敌的边不可以摧毁,让1和n无法连通的最大摧毁费用,就是1到n的最小割中的最大的那个,这个题卡了好几天,一开始是各种方法各种wa,后来无意中发现自己犯了个sb错误,结果改正后以前的各种方法各种ac,比赛要是碰到这样的事估计就跪了... 思路:
首先能确定的就是题目要求咱们就最小割(最大流 = 最小割),但关键是有那么一条无坚不摧的nb道路,所以一开始的想法肯定是暴力枚举N*N的边,直接TLE出翔了,那么就优化,记得以前的一道题目 给你一个图求删除其中一条边最短路中最大的那个,答案是只枚举最短路上的边就可以了, 这个题目也是类似,只要枚举最小割后两个集合的点组成的边就行了,因为假如点a和点b是一个集合的,那么把边ab变成无敌的没有意思,最小割的值不会改变,,那么怎么吧分成两个集合呢,两种方法,一个是深搜,这个方法容易理解,先跑一遍最大流,然后从点1开始深搜,如果当前点走过或者没有流量了(跑完一遍最大流后的流量),直接continue,这样被mark的点就是左集合的点,剩下的就是右集合的点,还有一种方法就是直接看DINIC后的deep数组,如果不等于-1就是左集合的,否则的就是右集合的,这个我结论是网上的,我还不知道为什么,分成两个集合后就可以枚举两个集合的点建枚举的边了,这块也有两个方法,一个就是之前不是跑一边最大流了吗,加上当前枚举边,直接在残余网络上跑,取得最大的max最后输出一开始那个最大流maxflow+max,(记得每次跑之前都还原成第一次跑完的残余网路),第二种方法就是直接重新建边,一开始的时候吧m条边记录下来,每次枚举都重新建图,然后加上枚举的边跑,最后输出的是最大流中最大的那个maxflow.下面是三种方法的代码.. 深搜找源集和汇集,在残余网络上跑 15ms AC
#include
#include
#include #define N_node 120 #define N_edge 22000
#define inf 1000000000 using namespace std; typedef struct {
int to ,next ,cost;
}STAR;
typedef struct
{
int x ,t;
}DEP; STAR E[N_edge] ,E_[N_edge];
DEP xin ,tou;
int list[N_node] ,list1[N_node] ,tot;
int list2[N_node];
int deep[N_node];
int mks[N_node] ,mks_;
int mkh[N_node] ,mkh_;
int mark[N_node]; void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot; E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
} int minn(int a ,int b)
{
return a < b ? a : b;
} bool BFS_DEEP(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s;
xin.t = 0;
queueq;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
list1[i] = list[i];
return deep[t] != -1;
} int DFS_MAX_FLOW(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = list1[s] ;k ;k = E[k].next)
{
list1[s] = k;
int to = E[k].to;
int c = E[k].cost;
if(deep[to] != deep[s] + 1||!E[k].cost)
continue;
int tmp = DFS_MAX_FLOW(to ,t ,minn(c ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(nowflow == flow)
break;
}
if(!nowflow)
deep[s] = 0;
return nowflow;
} int DINIC(int s ,int t ,int n)
{
int ans = 0;
while(BFS_DEEP(s ,t ,n))
{
ans += DFS_MAX_FLOW(s ,t ,inf);
}
return ans;
} void DFS(int s)
{
for(int k = list[s] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to] || !E[k].cost)
continue;
mark[to] = 1;
DFS(to);
}
return ;
} int main ()
{
int n ,m ,i ,j ,t;
int a ,b ,c;
scanf("%d" ,&t);
while(t--)
{
memset(list ,0 ,sizeof(list));
tot = 1;
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d %d" ,&a ,&b ,&c);
add(a ,b ,c);
}
int ans = DINIC(1 ,n ,n);
mks_ = mkh_ = 0;
memset(mark ,0 ,sizeof(mark));
mark[1] = 1;
DFS(1);
for(i = 2 ;i < n ;i ++)
if(mark[i]) mks[++mks_] = i;
else mkh[++mkh_] = i; for(i = 1 ;i <= tot ;i ++)
E_[i] = E[i];
int mktot = tot;
for(i = 1 ;i <= n ;i ++)
list2[i] = list[i]; int max = 0;
for(i = 1 ;i <= mks_ ;i ++)
for(j = 1 ;j <= mkh_ ;j ++)
{
a = mks[i] ,b = mkh[j];
for(int k = 1 ;k <= mktot ;k ++)
E[k] = E_[k];
memset(list ,0 ,sizeof(list));
for(int k = 1 ;k <= n ;k ++)
list[k] = list2[k];
tot = mktot;
add(a ,b ,inf);
int tmp = DINIC(1 ,n ,n);
if(max < tmp) max = tmp;
}
printf("%d\n" ,ans + max);
}
return 0;
} 根据deep数组找源集和汇集,在残余网络上跑 31ms AC #include
#include
#include #define N_node 120
#define N_edge 22000
#define inf 1000000000 using namespace std; typedef struct
{
int to ,next ,cost;
}STAR;
typedef struct
{
int x ,t;
}DEP; STAR E[N_edge] ,E_[N_edge];
DEP xin ,tou;
int list[N_node] ,list1[N_node] ,tot;
int list2[N_node];
int deep[N_node];
int mks[N_node] ,mks_;
int mkh[N_node] ,mkh_; void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot; E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
} int minn(int a ,int b)
{
return a < b ? a : b;
} bool BFS_DEEP(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s;
xin.t = 0;
queueq;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
list1[i] = list[i];
return deep[t] != -1;
} int DFS_MAX_FLOW(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = list1[s] ;k ;k = E[k].next)
{
list1[s] = k;
int to = E[k].to;
int c = E[k].cost;
if(deep[to] != deep[s] + 1||!E[k].cost)
continue;
int tmp = DFS_MAX_FLOW(to ,t ,minn(c ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(nowflow == flow)
break;
}
if(!nowflow)
deep[s] = 0;
return nowflow;
} int DINIC(int s ,int t ,int n)
{
int ans = 0;
while(BFS_DEEP(s ,t ,n))
{
ans += DFS_MAX_FLOW(s ,t ,inf);
}
return ans;
} int main ()
{
int n ,m ,i ,j ,t;
int a ,b ,c;
scanf("%d" ,&t);
while(t--)
{
memset(list ,0 ,sizeof(list));
tot = 1;
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d %d" ,&a ,&b ,&c);
add(a ,b ,c);
}
int ans = DINIC(1 ,n ,n);
mks_ = mkh_ = 0;
for(i = 2 ;i < n ;i ++)
if(deep[i] != -1) mks[++mks_] = i;
else mkh[++mkh_] = i; for(i = 1 ;i <= tot ;i ++)
E_[i] = E[i];
int mktot = tot;
for(i = 1 ;i <= n ;i ++)
list2[i] = list[i]; int max = 0;
for(i = 1 ;i <= mks_ ;i ++)
for(j = 1 ;j <= mkh_ ;j ++)
{
a = mks[i] ,b = mkh[j];
for(int k = 1 ;k <= mktot ;k ++)
E[k] = E_[k];
memset(list ,0 ,sizeof(list));
for(int k = 1 ;k <= n ;k ++)
list[k] = list2[k];
tot = mktot;
add(a ,b ,inf);
int tmp = DINIC(1 ,n ,n);
if(max < tmp) max = tmp;
}
printf("%d\n" ,ans + max);
}
return 0;
} 直接重新建图,深搜找源集和汇集(容易理解) 15msAC #include
#include
#include #define N_node 120
#define N_edge 22000
#define inf 1000000000 using namespace std; typedef struct
{
int to ,next ,cost;
}STAR;
typedef struct
{
int x ,t;
}DEP; typedef struct
{
int a ,b ,c;
}EDGE; STAR E[N_edge];
EDGE edge[N_edge];
DEP xin ,tou;
int list[N_node] ,list1[N_node] ,tot;
int deep[N_node];
int mks[N_node] ,mks_;
int mkh[N_node] ,mkh_;
int mark[N_node]; void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot; E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
} int minn(int a ,int b)
{
return a < b ? a : b;
} bool BFS_DEEP(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s;
xin.t = 0;
queueq;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
list1[i] = list[i];
return deep[t] != -1;
} int DFS_MAX_FLOW(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = list1[s] ;k ;k = E[k].next)
{
list1[s] = k;
int to = E[k].to;
int c = E[k].cost;
if(deep[to] != deep[s] + 1||!E[k].cost)
continue;
int tmp = DFS_MAX_FLOW(to ,t ,minn(c ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(nowflow == flow)
break;
}
if(!nowflow)
deep[s] = 0;
return nowflow;
} int DINIC(int s ,int t ,int n)
{
int ans = 0;
while(BFS_DEEP(s ,t ,n))
{
ans += DFS_MAX_FLOW(s ,t ,inf);
}
return ans;
} void DFS(int s)
{
for(int k = list[s] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to] || !E[k].cost)
continue;
mark[to] = 1;
DFS(to);
}
return ;
} int main ()
{
int n ,m ,i ,j ,t;
int a ,b ,c;
scanf("%d" ,&t);
while(t--)
{
memset(list ,0 ,sizeof(list));
tot = 1;
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d %d" ,&a ,&b ,&c);
add(a ,b ,c);
edge[i].a = a ,edge[i].b = b ,edge[i].c = c;
}
int ans = DINIC(1 ,n ,n);
mks_ = mkh_ = 0;
memset(mark ,0 ,sizeof(mark));
mark[1] = 1;
DFS(1);
for(i = 2 ;i < n ;i ++)
if(mark[i]) mks[++mks_] = i;
else mkh[++mkh_] = i;
for(i = 1 ;i <= mks_ ;i ++)
for(j = 1 ;j <= mkh_ ;j ++)
{
a = mks[i] ,b = mkh[j];
memset(list ,0 ,sizeof(list));
tot = 1;
for(int k = 1 ;k <= m ;k ++)
add(edge[k].a ,edge[k].b ,edge[k].c);
add(a ,b ,inf);
int tmp = DINIC(1 ,n ,n);
if(ans < tmp) ans = tmp;
}
printf("%d\n" ,ans);
}
return 0;
} ?

hdu 2435dinic算法模板+最小割性质的更多相关文章

  1. hdu 2435 dinic算法模板+最小割性质

    #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define ...

  2. hdu 4289 Control(最小割 + 拆点)

    http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  3. 洛谷.4897.[模板]最小割树(Dinic)

    题目链接 最小割树模板.具体见:https://www.cnblogs.com/SovietPower/p/9734013.html. ISAP不知为啥T成0分了.. Dinic: //1566ms ...

  4. HDU 4859 海岸线(最小割+最大独立点权变形)

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题意: 欢迎来到珠海!由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展.作为Z市的 ...

  5. [模板]最小割树(Gomory-Hu Tree)(luogu4897)

    给定一个\(n\)个点\(m\)条边的无向连通图,多次询问两点之间的最小割 两点间的最小割是这样定义的:原图的每条边有一个割断它的代价,你需要用最小的代价使得这两个点不连通 Input 第一行两个数\ ...

  6. HDU 4289 Control (最小割 拆点)

    Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  7. sw算法求最小割学习

    http://  blog.sina.com.cn/s/blog_700906660100v7vb.html 转载:http://www.cnblogs.com/ylfdrib/archive/201 ...

  8. King of Destruction HDU - 3002 && HDU - 3691(全局最小割)

    求无向图的最小割 有没有源点都一样,不影响 #include <iostream> #include <cstdio> #include <sstream> #in ...

  9. HDU.4700.Flow(构造 最小割树)

    题目链接 \(Description\) 给定\(n\)以及\(n\)个点任意两点之间的最大流,求一张无向图满足给定条件. \(n\leq100\). \(Solution\) 有些类似最小割树. 我 ...

随机推荐

  1. 项目产品化——Excel数据库模板化导入(java)

    Excel导入可能是代码开发中比較常见的功能,一个项目假设有多个地方须要excel导入数据库.那么开发的工作量也将比較大,项目产品化过程中,将这么一个类似的功能进行封装合并也是必要的.封装好的代码仅仅 ...

  2. 改你MB需求!

    改你MB需求! 原创 2015-12-08 尖峰视界 尖峰视界 我敏锐的觉察到,产品经理的头像開始闪动了.在0.1秒的时间内,我全身的血液都冲向了大脑.果然.右上角弹出了文件传输窗体. "最 ...

  3. python:sql建表语句转换为json

    第一种sql格式: CREATE TABLE prpcitem_car ( proposalno ) NOT NULL, itemno ,) NOT NULL, riskcode ) NOT NULL ...

  4. Linux学习之设置联网,关闭防火墙,关闭selinux

    桥接模式,给一台物理机,有自己独立的IP. boot分区,引导分区,系统启动,内核文件. swap分区,内存扩展分区.1.5或2倍.内存不够的时候,会写入其中.正常给8G或者16G就够了.不需要非要1 ...

  5. Softmax回归——logistic回归模型在多分类问题上的推广

    Softmax回归 Contents [hide] 1 简介 2 代价函数 3 Softmax回归模型参数化的特点 4 权重衰减 5 Softmax回归与Logistic 回归的关系 6 Softma ...

  6. 【转】不要使用SBJSON(json-framework)

    原文网址:http://blog.devtang.com/2012/05/05/do-not-use-sbjson/ 不知道为什么,在iOS开发中,有很多人使用 SBJSON (又被称作json-fr ...

  7. 框架:Rureka

    ylbtech-框架:Rureka Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的.S ...

  8. css中!important的用法

    {*rule !important}这个css规则当今在网页制作的时候的普及已经非常流行了,以前我对它的理解就停留在‘浏览器是否识别阶段’ 而没有真正去研究过,可是现在发生了变化.众所周知,!impo ...

  9. vmware笔试题目

    http://discuss.acmcoder.com/topic/58db8e2ebb0f44ba0e94e670 上面是完整的题目,下面一下我自己的想法. http://discuss.acmco ...

  10. Prism学习(1)---前期准备

    本文摘取自Gene's Blog的博客园文章,版权归Gene's Blog,仅供个人学习参考.转载请标明原作者Gene's Blog. 在学习Prism框架之前,我预先写了一个非常简单的计算器解决方案 ...