您的位置:首页 > 理论基础 > 计算机网络

hihocoder 1378 网络流二·最大流最小割定理

2017-09-05 17:02 344 查看
题目链接:网络流二·最大流最小割定理

题目大意:给你一张有向图,算最小割,最小割集的点数个数和个数编号

题目思路:跑一边最大流可以得到最小割,这个是显而易见的,要找最小割集,我们只需要最后再跑一遍BFS就好了,这个时候一定是找不到增广路的,所以这时候访问到的点就是最小割集了,记录一下就好了

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 1000+100;
const int MAXM = 1000000+10;
const int INF = 1000000+10;

struct Edge{
int from, to, cap, flow, next;
}edge[MAXM];

int dist[MAXN], vis[MAXN], cur[MAXN], top, head[MAXN];
int n, m;
int sumflow;
int sink;
int num;
bool flag;

void init(){
top = 0;
memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w){
Edge E1 = {u, v, w, 0, head[u]};
edge[top] = E1;
head[u] = top++;
Edge E2 = {v, u, 0, 0, head[v]};
edge[top] = E2;
head[v] = top++;
}

bool BFS(int start, int End){
queue<int> Q;
memset(dist, -1, sizeof(dist));
memset(vis, 0, sizeof(vis));
while(!Q.empty()) Q.pop();
Q.push(start);
vis[start] = 1;
dist[start] = 0;
if(flag) num++;
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int i = head[u]; i != -1; i = edge[i].next){
Edge E = edge[i];
if(!vis[E.to] && E.cap > E.flow){
vis[E.to] = 1;
dist[E.to] = dist[u] + 1;
if(!flag&&E.to == End) return true;
if(flag) num++;
Q.push(E.to);
}
}
}
return false;
}
int DFS(int x, int a, int End){
if(x == End || a == 0) return a;
int flow = 0, f;
for(int& i = cur[x]; i != -1; i = edge[i].next){
Edge& E = edge[i];
if(dist[E.to] == dist[x]+1 && (f = DFS(E.to, min(a, E.cap-E.flow), End)) > 0){
E.flow += f;
edge[i^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Dinic(int start, int End){
int flow = 0;
while(BFS(start, End)){
memcpy(cur, head, sizeof(head));
flow += DFS(start, INF, End);
}
flag = true;
BFS(1,n);
return flow;
}

int main(){
int T,u,v,cost;
init();
num = 0;
scanf("%d%d",&n,&m);
while(m--){
scanf("%d%d%d",&u,&v,&cost);
addedge(u,v,cost);
}
printf("%d ",Dinic(1,n));
printf("%d\n",num);
for(int i = 1;i <= n;i++){
if(vis[i]) printf("%d ",i);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: