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

POJ 3469 网络流最小割

2015-02-10 15:43 190 查看
将两个CPU分别视作源点和汇点

对于那些不在同一个CPU中的模块会产生的代价作为一条双向的容量弧

这里每个模块可以在任意一个CPU中运行,相当于寻找一个割,分割后,在S集合中的模块安装在第一个CPU中

那么在T集合中的模块就是在第二个CPU中,所求的最小割也正是最小耗费

根据最大流=最小割的原理,这里相当于是在求最大流

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>

using namespace std;
const int N = 20010;
const int INF = 0x3f3f3f3f;
int lev
,first
,k;

struct Edge{
int u , v , cap , flow , next;
}e[N*30];

void add_edge(int u , int v , int cap)
{
e[k].u=u , e[k].v = v , e[k].cap=cap , e[k].flow=0 , e[k].next = first[u];
first[u]=k++;
}
//寻找层次网络是否存在
bool find_level(int n)
{
queue<int> q;
q.push(0);
memset(lev , 0 , sizeof(lev));
lev[0]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=first[u] ; i!=-1 ; i=e[i].next){
int v = e[i].v;
if(!lev[v] && e[i].cap > e[i].flow){
lev[v] = lev[u]+1;
q.push(v);
}
}
}
return lev[n+1]>0;
}

int Dinic(int n , int u , int sum)
{
int s = sum , t;
if(u == n+1) return sum;
for(int i=first[u] ; i!=-1 ;i=e[i].next)
{
int v = e[i].v;
if(lev[v] != lev[u]+1 || e[i].cap <= e[i].flow) continue;
t = Dinic(n , v , min(sum , e[i].cap - e[i].flow));
e[i].flow += t;
e[i^1].flow -= t;
sum-=t;
}
return s-sum;
}

int main()
{
// freopen("a.in" , "r" , stdin);
int n , m , u , v , cap1 , cap2;
while(scanf("%d%d" , &n , &m) == 2)
{
k=0;
memset(first , -1 , sizeof(first));
for(int i=0 ; i<n ; i++)
{
scanf("%d%d" , &cap1 , &cap2);
//添加双向弧
add_edge(0 , i+1 , cap1);
add_edge(i+1 , 0 , 0);

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