J - Sabotage - UVA 10480(最大流)
2015-08-11 10:05
309 查看
题目大意:旧政府有一个很庞大的网络系统,可以很方便的指挥他的城市,起义军为了减少伤亡所以决定破坏他们的网络,使他们的首都(1号城市)和最大的城市(2号城市)不能联系,不过破坏不同的网络所花费的代价是不同的,现在起义军想知道最少花费的代价是多少,输出需要破坏的线路。
输入:第一行输入一个N和M,表示城市数和线路数,下面M行,每行有三个整数,表示从破坏城市u到v的线路花费是w。 分析:很明显的最小割问题,我们知道有向图(题目给的是无向图,所以需要建立反边)的最小割等于最大流,所以只需要求出来最大流即可,不过答案需要输出的是路线,其实也很容易解决,在求出来最大流后的残余网络中,只要源点能够到达的点都属于源点集合,到达不了的属于汇点集合,这样就把整个网络分成了两部分,如果原来这两部分有线路连接,那么这条线路肯定是被破坏的,把它输出就行了。下面是AC代码。=============================================================================================================================#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
const int MAXN = 105;
const int oo = 1e9+7;
int G[MAXN][MAXN], Layer[MAXN];
int x[MAXN*5], y[MAXN*5];
bool BFS(int start, int End, int N)
{
memset(Layer, 0, sizeof(Layer));
queue<int> Q; Q.push(start);
Layer[start] = 1;
while(Q.size())
{
int i = Q.front();Q.pop();
if(i == End)return true;
for(int j=1; j<=N; j++)
{
if(!Layer[j] && G[i][j])
{
Layer[j] = Layer[i] + 1;
Q.push(j);
}
}
}
return false;
}
int DFS(int i, int MaxFlow, int End, int N)
{
if(i == End)return MaxFlow;
int iflow = 0;
for(int j=1; j<=N; j++)
{
if(Layer[j]-1 == Layer[i] && G[i][j])
{
int flow = min(MaxFlow-iflow, G[i][j]);
flow = DFS(j, flow, End, N);
G[i][j] -= flow;
G[j][i] += flow;
iflow += flow;
if(iflow == MaxFlow)
break;
}
}
if(iflow == 0)
Layer[i] = 0;
return iflow;
}
int Dinic(int start, int End, int N)
{
int MaxFlow = 0;
while( BFS(start, End, N) == true )
MaxFlow += DFS(start, oo, End, N);
return MaxFlow;
}
int main()
{
int N, M;
while(scanf("%d%d", &N, &M) != EOF && M+N)
{
int i, u, v, flow;
int w[MAXN][MAXN]={0};
memset(G, 0, sizeof(G));
for(i=1; i<=M; i++)
{
scanf("%d%d%d", &u, &v, &flow);
x[i] = u, y[i] = v;
G[u][v] = G[v][u] = flow;
w[u][v] = w[v][u] = flow;
}
Dinic(1, 2, N);
for(i=1; i<=M; i++)
{
if(!Layer[x[i]] && Layer[y[i]] || Layer[x[i]] && !Layer[y[i]])
printf("%d %d\n", x[i], y[i]);
}
printf("\n");
}
return 0;
}
输入:第一行输入一个N和M,表示城市数和线路数,下面M行,每行有三个整数,表示从破坏城市u到v的线路花费是w。 分析:很明显的最小割问题,我们知道有向图(题目给的是无向图,所以需要建立反边)的最小割等于最大流,所以只需要求出来最大流即可,不过答案需要输出的是路线,其实也很容易解决,在求出来最大流后的残余网络中,只要源点能够到达的点都属于源点集合,到达不了的属于汇点集合,这样就把整个网络分成了两部分,如果原来这两部分有线路连接,那么这条线路肯定是被破坏的,把它输出就行了。下面是AC代码。=============================================================================================================================#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
const int MAXN = 105;
const int oo = 1e9+7;
int G[MAXN][MAXN], Layer[MAXN];
int x[MAXN*5], y[MAXN*5];
bool BFS(int start, int End, int N)
{
memset(Layer, 0, sizeof(Layer));
queue<int> Q; Q.push(start);
Layer[start] = 1;
while(Q.size())
{
int i = Q.front();Q.pop();
if(i == End)return true;
for(int j=1; j<=N; j++)
{
if(!Layer[j] && G[i][j])
{
Layer[j] = Layer[i] + 1;
Q.push(j);
}
}
}
return false;
}
int DFS(int i, int MaxFlow, int End, int N)
{
if(i == End)return MaxFlow;
int iflow = 0;
for(int j=1; j<=N; j++)
{
if(Layer[j]-1 == Layer[i] && G[i][j])
{
int flow = min(MaxFlow-iflow, G[i][j]);
flow = DFS(j, flow, End, N);
G[i][j] -= flow;
G[j][i] += flow;
iflow += flow;
if(iflow == MaxFlow)
break;
}
}
if(iflow == 0)
Layer[i] = 0;
return iflow;
}
int Dinic(int start, int End, int N)
{
int MaxFlow = 0;
while( BFS(start, End, N) == true )
MaxFlow += DFS(start, oo, End, N);
return MaxFlow;
}
int main()
{
int N, M;
while(scanf("%d%d", &N, &M) != EOF && M+N)
{
int i, u, v, flow;
int w[MAXN][MAXN]={0};
memset(G, 0, sizeof(G));
for(i=1; i<=M; i++)
{
scanf("%d%d%d", &u, &v, &flow);
x[i] = u, y[i] = v;
G[u][v] = G[v][u] = flow;
w[u][v] = w[v][u] = flow;
}
Dinic(1, 2, N);
for(i=1; i<=M; i++)
{
if(!Layer[x[i]] && Layer[y[i]] || Layer[x[i]] && !Layer[y[i]])
printf("%d %d\n", x[i], y[i]);
}
printf("\n");
}
return 0;
}
相关文章推荐
- 使用命令远程注销服务器
- jquery删除某数组某几个下标的元素
- HDOJ 畅通工程再续(最小生成树--prime)
- jQuery中prepend()方法使用详解
- PHP实现删除字符串中任何字符的函数
- jsp页面的加载顺序
- 正则表达式
- linux 查看系统信息命令(比较全)
- 18-Map集合-08-常用对象API(集合框架-Map集合-TreeMap存储自定义对象)
- POJ 3041 Asteroids 匈牙利算法 最小点覆盖
- 程序员很穷
- PHP面向对象(OOP):__toString()方法
- Creating Isomorphic Apps with Node.js, React, and Express
- 转转
- 编译原理第一章学习总结
- poj 1258 Agri-Net 【Prim&Kruskal】
- CodeVS 1213 解的个数
- Java I/O 操作及优化建议
- 201508110842_《Javascript权威指南(第六版)——方法借用,私有状态,construct重构和工厂方法》(P225-233)
- @清晰掉 GNU C __attribute__