HDU 2435 There is a war Dinic 最小割
题意是有n座城市,n号城市不想让1号城市可达n号,每条道路有一条毁坏的代价,1号还可以修一条不能毁坏的道路,求n号城市所需的最小代价最大是多少。
毁坏的最小代价就直接求一遍最大流,就是最小割了。而可以修一条不能毁坏的路,需要枚举的这些边就是源集中的点到汇集中的点,我之前的做法是直接找出所有的割边,再枚举每一条割边,在这两个点上加一个流量为无穷大的边再去求最大流,实际上这样连样例的第二个数据都过不了,因为图不保证是连通的,那就有一些源集中的点和汇集中的点本来就不联通,就不存在这样的割边了。发现这个错误后,我就在没有联通的所有边中加了一条cap为0的边,想弥补上面的bug,但是这样的话超时了。奇怪的是,我没有加那些cap为0的点的时候也是超时而不是wa。
所以就找出所有的源点,找出所有的汇点,去除1和n后枚举这些边在原来的基础上去跑最大流,得出来的意义就是如果修的是这条路,所需要的额外的代价。
我自己的代码不知道为什么过不了,可能是模板的问题?
贴两个代码吧,前面是自己的,后面是别人的。
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define LL long long
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MAXN 105
#define OPEN_FILE
using namespace std;
int S;
struct Edge{
int from, to, cap, flow;
//Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){};
};
vector<Edge> cutset;
bool comp(const Edge& a, const Edge& b){
return (a.from < b.from || (a.from == b.from && a.to < b.to));
}
struct Dinic{
int n, m, i, s, t;
Edge e;
vector<Edge> edges;
vector<int> G[MAXN];
int d[MAXN], cur[MAXN];
// bool vis[MAXN];
int Q[MAXN * ]; void init(int n){
this->n = n;
for (i = ; i <= n; i++){
G[i].clear();
}
edges.clear();
}
void AddEdge(int from, int to, int cap){
edges.push_back(Edge{ from, to, cap, });
edges.push_back(Edge{ to, from, , });
m = edges.size();
G[from].push_back(m - );
G[to].push_back(m - );
}
bool BFS(){
// memset(vis, 0, sizeof(vis));
int head = , tail = ;
Q[head] = s;
memset(d, , sizeof(d));
d[s] = ;
S = ;
while (head <= tail){
int x = Q[head++];
for (i = ; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (d[e.to] == && e.cap > e.flow){
d[e.to] = d[x] + ;
Q[++tail] = e.to;
S++;
}
}
}
if (d[t] == ){
return false;
}
else{
return true;
}
}
int DFS(int x, int a){
if (x == t || a == ) return a;
int flow = , f;
for (int& i = cur[x]; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (d[x] + == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > ){
e.flow += f;
edges[G[x][i] ^ ].flow -= f;
flow += f;
a -= f;
if (a == ) break;
}
}
return flow;
}
int MaxFlow(int s, int t, int need){
int flow = ;
this->s = s;
this->t = t;
while (BFS()){
memset(cur, , sizeof(cur));
flow += DFS(s, INF);
if (flow > need) return flow;
}
return flow;
}
};
int n, m;
Dinic p, q;
int RIGHT[MAXN];
int main()
{
#ifdef OPEN_FILE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // OPEN_FILE
int T;
scanf("%d", &T);
for (int cas = ; cas <= T; cas++){
scanf("%d%d", &n, &m);
p.init(n);
int x, y, z;
// memset(conn, 0, sizeof(conn));
for (int i = ; i <= m; i++){
scanf("%d%d%d", &x, &y, &z);
p.AddEdge(x, y, z);
// conn[x][y] = true;
//conn[y][x] = true;
}
//int res = p.MaxFlow(1, n, INF);
//p.AddEdge(2, 3, INF);
//q = p;
int res = p.MaxFlow(, n, INF);
int cnt = ;
// memset(isR, 0, sizeof(isR));
for (int i = ; i < n; i++){
if (p.d[i] == ){
RIGHT[cnt++] = i;
}
}
cnt--;
int ans = ;
for (int i = ; i <= S; i++){
if (p.Q[i] == || p.Q[i] == n) continue;
for (int j = ; j <= cnt; j++){
q = p;
q.AddEdge(p.Q[i], RIGHT[j], INF);
int o = q.MaxFlow(, n, INF);
ans = max(ans, o);
}
}
// int ans = 0;
// for (int i = 0; i < cutset.size(); i++){
// q = p;
// q.AddEdge(cutset[i].from, cutset[i].to, INF);
// int o = q.MaxFlow(1, n, INF);
// ans = max(ans, o);
// }
printf("%d\n", ans + res);
// printf("%d\n", p.MaxFlow(1, n, INF));
}
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cstdio>
#include<string>
#include <algorithm>
using namespace std;
const int maxn = ;
//const int maxm=300006;
const int inf = << ; struct node
{
int v, next;
int val;
};
int topset;
struct dinic{
node s[maxn*maxn * ]; int level[maxn];//顶点的层次
int p[maxn];
int que[maxn * ];//BFS中用于遍历的顶点,DFS求增广中记录边
int out[ * maxn];//DFS用于几乎定点的分支
int ind; int cop_poit[maxn];
node cop_mp[maxn*maxn * ]; void init()
{
ind = ;
memset(p, -, sizeof(p));
} inline void insert(int x, int y, int z)
{
s[ind].v = y;
s[ind].val = z;
s[ind].next = p[x];
p[x] = ind++;
s[ind].v = x;
s[ind].val = ;
s[ind].next = p[y];
p[y] = ind++;
} int max_flow(int n, int source, int sink)
{
int ret = ;
int h = , r = ;
while ()//DFS
{
int i;
for (i = ; i <= n; ++i)
level[i] = ;
h = , r = ;
level[source] = ;
que[] = source;
while (h <= r)//BFS
{
int t = que[h++];
for (i = p[t]; i != -; i = s[i].next)
{
if (s[i].val&&level[s[i].v] == )
{
level[s[i].v] = level[t] + ;
que[++r] = s[i].v;
}
}
}
topset = r;//记录原点的集合个数 if (level[sink] == )break;//找不到汇点
for (i = ; i <= n; ++i)
out[i] = p[i]; int q = -;
while ()
{
if (q < )
{
int cur = out[source];
for (; cur != -; cur = s[cur].next)
{
if (s[cur].val&&out[s[cur].v] != - && level[s[cur].v] == )
{
break;
}
}
if (cur >= )
{
que[++q] = cur;
out[source] = s[cur].next;
}
else
{
break;
}
} int u = s[que[q]].v; if (u == sink)//一条增广路
{
int dd = inf;
int index = -;
for (i = ; i <= q; i++)
{
if (dd > s[que[i]].val)
{
dd = s[que[i]].val;
index = i;
}
}
ret += dd;
//cout<<ret<<endl;
for (i = ; i <= q; i++)
{
s[que[i]].val -= dd;
s[que[i] ^ ].val += dd;
}
for (i = ; i <= q; i++)
{
if (s[que[i]].val == )
{
q = index - ;
break;
}
}
}
else
{
long cur = out[u];
for (; cur != -; cur = s[cur].next)
{
if (s[cur].val&&out[s[cur].v] != - && level[u] + == level[s[cur].v])
{
break;
}
}
if (cur != -)
{
que[++q] = cur;
out[u] = s[cur].next;
}
else
{
out[u] = -;
q--;
}
}
}
}
return ret;
}
}; int m, n;
int q[maxn * ];
dinic x, y;
int main()
{
freopen("in.txt", "r", stdin);
int cas;
cin >> cas;
int huijie[maxn];
while (cas--)
{
x.init();
scanf("%d%d", &n, &m);
for (int i = ; i < m; i++)
{
long from, to, cost;
scanf("%d %d %d", &from, &to, &cost);
x.insert(from, to, cost);
}
long Start, End;
Start = ; End = n;
int tmp = x.max_flow(n, Start, End);//计算一次最大流(最小割) y = x; int ans = ;
int r = ; for (int j = ; j < n; j++)//求出汇集---因为bfs找不到一条增广路时,qu中就是原集,剩下来就是汇集,也可以是leve数组便利不到的顶点
{
if (x.level[j] == )
huijie[r++] = j;
} for (int i = ; i <= topset; i++)//枚举两顶点
{
if (x.que[i] == || x.que[i] == n) continue;
for (int j = ; j < r; j++)
{
y = x;
y.insert(x.que[i], huijie[j], inf);//加边
int g = y.max_flow(n, , n);//格外的代价
ans = max(ans, g);
}
}
printf("%d\n", ans + tmp);
}
return ;
}
HDU 2435 There is a war Dinic 最小割的更多相关文章
- HDU 2435 There is a war (网络流-最小割)
There is a war Problem Description There is a sea. There are N islands in the sea. ...
- HDU 2435 There is a war
There is a war Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ...
- POJ 1815 Friendship (Dinic 最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 8025 Accepted: 2224 Descri ...
- HDU 2676 Network Wars 01分数规划,最小割 难度:4
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1676 对顶点i,j,起点s=1,终点t=n,可以认为题意要求一组01矩阵use ...
- HDU 6214 Smallest Minimum Cut(最少边最小割)
Problem Description Consider a network G=(V,E) with source s and sink t. An s-t cut is a partition o ...
- hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)
要选出一些点,这些点之间没有相邻边且要求权值之和最大,求这个权值 分析:二分图带权最大独立集. 用最大流最小割定理求解.其建图思路是:将所有格点编号,奇数视作X部,偶数视作Y部,建立源点S和汇点T, ...
- HDU 6214 Smallest Minimum Cut 【网络流最小割+ 二种方法只能一种有效+hdu 3987原题】
Problem Description Consider a network G=(V,E) with source s and sink t . An s-t cut is a partition ...
- HDU - 5457 Hold Your Hand (Trie + 最小割)
Hold Your Hand Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)T ...
- 【hdu 4859】海岸线(图论--网络流最小割)
题意:有一个区域,有'.'的陆地,'D'的深海域,'E'的浅海域.其中浅海域可以填充为陆地.这里的陆地区域不联通,并且整个地图都处在海洋之中.问填充一定浅海域之后所有岛屿的最长的海岸线之和. 解法:最 ...
随机推荐
- 题解 洛谷 P1580 【yyy loves Easter_Egg I】
一言不合上代码: #include<cstdio> #include<cstring> ],bz[],dmz[]; int maohao,xf,ls,sss,lll,xxf,x ...
- Qt之字体文件(TTF)
简述 TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式,随着windows的流行,已经变成最常用的一种字体文件表示方式. 在一些特殊的场合,系统字符集不 ...
- 如何用一次性密码通过 SSH 安全登录 Linux
有人说,安全不是一个产品,而是一个过程.虽然 SSH 协议被设计成使用加密技术来确保安全,但如果使用不当,别人还是能够破坏你的系统:比如弱密码.密钥泄露.使用过时的 SSH 客户端等,都能引发安全问题 ...
- hadoop 多文件夹输入,map到reduce怎样排序
使用MultipleInputs.addInputPath 对多个路径输入 如今如果有三个文件夹,并使用了三个mapper去处理, 经过map处理后,输出的结果会依据key 进行join, 假设使用T ...
- Android jni 二维数组 传递
学习Android Jni时,一个二维 整数 数组的传递花了我好长时间,在网上查的资料都不全,当然最后是成功了,写在这里是为了自己记住,当然有人搜索到并利用了我会很高兴. in Android J ...
- 查看suse系统版本
cat /etc/*-release OR lsb_release -d
- php7安装memcache 和 memcached 扩展
php7安装memcache 和 memcached 扩展 标签(空格分隔): php memcache和memcached区别 memcache:http://pecl.php.net/packag ...
- iOS菜鸟成长笔记(2)——网易彩票练习
距离上一篇<第一个iOS应用>已经有一个多月了,今天来和大家一起学习和分享一下一个小练习<网易彩票> 首先我们向storyboard中拖入一个TabBarController和 ...
- Matlab函数编译成dll供c调用
一 编译dll 在Command Window窗口中输入mbuild -setup,然后会出现语句,是否安装编译器,选择n,因为机子上已经安装了C/C++/C#的编译器,选择VS2010.
- sql笔试题-1
在oracle下sql:比较巧妙地是group by 部分 E from (select a.team,b.y from nba a,nba b ) c group by (c.y-rownum) o ...