题意是有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. 实验二实验结论&实验总结与体会

    Part1:格式化输出函数printf()和格式化输入函数scanf() ① /* <C语言程序设计教程学习指导>p118 实验内容(1) 这是一个常用格式控制符使用示例 运行程序,结合运 ...

  2. C/C++ ShellExecuteEx调用exe可执行文件

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/49591995 以商业的软件Enblen ...

  3. FS,FT,DFT,DFS和DTFT的关系

    对于初学数字信号(Digital Signal Processing,DSP)的人来说,这几种变换是最为头疼的,它们是数字信号处理的理论基础,贯穿整个信号的处理. FS:时域上任意连续的周期信号可以分 ...

  4. IntelliJ IDEA 进行Maven项目创建build

    IntelliJ IDEA 进行Maven项目创建build 1,文件-新建-maven 项目:2,编写pom.xml文件:3,鼠标放到左下,然后选择Maven Projects,然后可以查看项目信息 ...

  5. STL_算法_查找算法(binary_search、includes)

    C++ Primer 学习中.. . 简单记录下我的学习过程 (代码为主) 全部容器适用(O(log(n)))     已序区间查找算法 binary_search             //二分查 ...

  6. JConsole远程监控Tomcat7

    下面技术应用于最优质的水果的鲜果篮 一.设置服务端: 1.增加Listener到conf/server.xml <Listener className="org.apache.cata ...

  7. HDU 5310 Souvenir

    Souvenir  Accepts: 901  Submissions: 2743  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 262 ...

  8. m_Orchestrate learning system---二十五、复制类的时候最容易出现的错误是什么

    m_Orchestrate learning system---二十五.复制类的时候最容易出现的错误是什么 一.总结 一句话总结:命名空间错误导致Analyze类虽然继承了Base类,但是没有执行里面 ...

  9. DDos游戏行业受攻击最多

    游戏行业遭遇DDOS攻击现状. 游戏一直是最易遭受黑客攻击的行业,高居全年DDOS攻击的48%.大规模攻击居多,平均值均超过100Gbps,攻击峰值急速上升,同比2015年增加了137.1%,其中攻击 ...

  10. rest_framework-认证-总结完结篇

    执行过程 APIView() Ruquest() Authentication() OrderView()APIView() def duspatch: self.initial(request) d ...