题意是有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 最小割的更多相关文章

  1. HDU 2435 There is a war (网络流-最小割)

    There is a war Problem Description       There is a sea.       There are N islands in the sea.       ...

  2. HDU 2435 There is a war

    There is a war Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ...

  3. POJ 1815 Friendship (Dinic 最小割)

    Friendship Time Limit: 2000MS   Memory Limit: 20000K Total Submissions: 8025   Accepted: 2224 Descri ...

  4. HDU 2676 Network Wars 01分数规划,最小割 难度:4

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1676 对顶点i,j,起点s=1,终点t=n,可以认为题意要求一组01矩阵use ...

  5. 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 ...

  6. hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)

    要选出一些点,这些点之间没有相邻边且要求权值之和最大,求这个权值 分析:二分图带权最大独立集. 用最大流最小割定理求解.其建图思路是:将所有格点编号,奇数视作X部,偶数视作Y部,建立源点S和汇点T, ...

  7. 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 ...

  8. HDU - 5457 Hold Your Hand (Trie + 最小割)

    Hold Your Hand Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)T ...

  9. 【hdu 4859】海岸线(图论--网络流最小割)

    题意:有一个区域,有'.'的陆地,'D'的深海域,'E'的浅海域.其中浅海域可以填充为陆地.这里的陆地区域不联通,并且整个地图都处在海洋之中.问填充一定浅海域之后所有岛屿的最长的海岸线之和. 解法:最 ...

随机推荐

  1. 紫书 习题 11-10 UVa 12264 (二分答案+最大流)

    书上写的是UVa 12011, 实际上是 12264 参考了https://blog.csdn.net/xl2015190026/article/details/51902823 这道题就是求出一种最 ...

  2. solr + eclipse 调试环境搭建

    1: 在官网下载对应源码 http://www.fayea.com/apache-mirror/lucene/solr/4.1.0/ 选择源码文件,如图所示: 2: 解压后目录如图所示: 在根目录下存 ...

  3. [Javascript] Required function arguments in Javascript

    In Javascript, all function arguments are optional by default. That means if you ever forget to pass ...

  4. 在使用shape的同一时候,用代码改动shape的颜色属性

    Android里面常常会使用shape来定制一些View的背景 能够改动View的背景颜色.形状等属性 普通情况下.shape都是在xml文件中面写死了.今天遇到一个需求,View的形状是圆角的,可是 ...

  5. 一起talk C栗子吧(第九十五回:C语言实例--使用共享内存进行进程间通信一)

    各位看官们,大家好,上一回中咱们说的是SystemV IPC结构概述的样例,这一回咱们说的样例是:使用共享内存进行进程间通信. 闲话休提.言归正转.让我们一起talk C栗子吧! 共享内存是Syste ...

  6. Data Member Order

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-member-order In some appl ...

  7. Android JNI和NDK学习(09)--JNI实例二 传递类对象

    1 应用层代码 NdkParam.java是JNI函数的调用类,它的代码如下:   package com.skywang.ndk; import android.app.Activity; impo ...

  8. A list is a sequence

    Like a string, a list is a sequence of values. In a string, the values are characters; in a list, th ...

  9. POJ 3667 线段树+标记

    自从某次考试写线段树写挂了以后 这是第一次写线段树,,,,,, 这是一个伤心的故事-- 题意: 思路: 标记 维护从左到右的最大值 从右到左的最大值 区间内的最大值-- 然后就一搞 就出来了 //By ...

  10. 美国人教你这样用Google,你真的会变特工

    转自微博:黑客师: 用了这么久的谷歌,今天才发现. 第一篇 在搜索框上输入:“indexof/”inurl:lib 再按搜索你将进入许多图书馆,并且一定能下载自己喜欢的书籍. 在搜索框上输入:“ind ...