题意是有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. Linux 和 Windows 双系统时间同步问题 修改注册表

    路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation 1:新建  >> DWORD(32 b ...

  2. nginx编译支持HTTP2.0

    nginx编译支持HTTP2.0 nginx编译支持HTTP2.0 wget https://www.openssl.org/source/openssl-1.1.0i.tar.gz #openssl ...

  3. curl命令查看响应时间

    curl -w "%{time_namelookup}::%{time_connect}::%{time_starttransfer}::%{time_total}::%{speed_dow ...

  4. codevs1281 矩阵乘法 快速幂 !!!手写乘法取模!!! 练习struct的构造函数和成员函数

    对于这道题目以及我的快速幂以及我的一节半晚自习我表示无力吐槽,, 首先矩阵乘法和快速幂没必要太多说吧,,嗯没必要,,我相信没必要,,实在做不出来写两个矩阵手推一下也就能理解矩阵的顺序了,要格外注意一些 ...

  5. xp秘钥

    TDCXC-M9FW9-3HQ28-CPXYR-YXQ3QCCBDF-9W9T8-K8B7M-83HJM-X2MCWP3MF6-BTDKT-KR7YF-X4BM9-4HD9TMCCWF-42JGF-W ...

  6. Python: PS 图像调整--颜色梯度

    本文用 Python 实现 PS 中的色彩图,可以看到颜色的各种渐变,具体的效果可以参考以前的博客: http://blog.csdn.net/matrix_space/article/details ...

  7. [BZOJ3884] 上帝与集合的正确用法 (欧拉函数)

    题目链接:  https://www.lydsy.com/JudgeOnline/problem.php?id=3884 题目大意: 给出 M, 求 $2^{2^{2^{2^{...}}}}$ % M ...

  8. 学golang之前都需要哪些前置知识?

    我学golang,感觉前面基础语法部分都很快能学会,但是到了goroutine,channel等后面的部分就看不懂了,是不是我学这个之前还得学习其他什么知识啊?(我有C语言基础,对于C语言里面的指针, ...

  9. mybatis如何成功插入后获取自增长的id

    使用mybatis向数据库中插入一条记录,如何获取成功插入记录的自增长id呢? 需要向xml配置中加上一下两个配置: <insert id="add" useGenerate ...

  10. poj2104 K-th Number(划分树)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 66068   Accepted: 23273 Ca ...