这题建图方式:第一核做源点(S = 0),第二核做汇点(T = N +1),每个模块的双核花费<Ai, Bi>,加边<S, i, Ai>, <i, T, Bi>,如果不在同一核上操作,虚假额外花费,即加双向容量,加边<a, b, w>, <b, a, w>。剩下的就是实现方法了,我这里用dinic来实现的。
今天学习了下dinic,学的一头雾水,对着模板敲,终于过了,稍稍懂了点什么叫dinic,原来dinic是层次化思想,每次不是回到源点搜,而是回到找到最小增流的地方继续增广。2007年论文《浅谈基于分层思想的网络流算法》有讲解,具体步骤可以分成四点:
1、初始化流量,计算出剩余图
2、一次bfs对顶点标号,计算出层次图,如果汇点不在层次图内,那么算法结束
#include < stdio.h >
#include < stdlib.h >
#include < string .h >
#define MM 480008
#define NN 20004
#define INF 0xfffffff
typedef struct node{
int adjVer, wet, nxt;
}edgeNode;
edgeNode edg[MM];
int link[NN];
int h[NN];
int M, N, idx, S, T;
int Min( int a, int b){
return a < b ? a : b;
}
void add( int u, int v, int x, int y){
edg[idx].adjVer = v;
edg[idx].wet = x;
edg[idx].nxt = link[u];
link[u] = idx ++ ;
edg[idx].adjVer = u;
edg[idx].wet = y;
edg[idx].nxt = link[v];
link[v] = idx ++ ;
}
/* 找到层次图 */
int bfs()
{
int i, head, tail, u, v, w, tmp;
int que[NN];
for (i = 0 ; i <= N + 1 ; i ++ ) h[i] = - 1 ;
que[ 0 ] = S;
h[S] = 0 ;
head = tail = 0 ;
while (head <= tail){
u = que[head ++ ];
for (tmp = link[u]; tmp != - 1 ; tmp = edg[tmp].nxt){
v = edg[tmp].adjVer;
w = edg[tmp].wet;
if (h[v] == - 1 && w > 0 ){
h[v] = h[u] + 1 ;
que[ ++ tail] = v;
}
}
}
return h[T] != - 1 ;
}
int dfs( int u, int flow){
if (u == T) return flow;
int tmpf, minf, v, w, tmp;
tmpf = 0 ;
for (tmp = link[u]; tmp != - 1 ; tmp = edg[tmp].nxt){
v = edg[tmp].adjVer;
w = edg[tmp].wet;
if (h[v] == h[u] + 1 && w > 0 && tmpf < flow && (minf = dfs(v, Min(w, flow - tmpf)))){
edg[tmp].wet -= minf;
edg[tmp + ! (tmp % 2 )].wet += minf; // 将反向边也更改一下,由于正反向边是相邻加入边的,所以可以这样来改
tmpf += minf;
}
}
if (tmpf == 0 ){
h[u] = - 1 ;
}
return tmpf;
}
void dinic()
{
int t, ans = 0 ;
while (bfs()){
while (t = dfs(S, INF))
ans += t;
}
printf( " %d\n " , ans);
}
int main()
{
int i, a, b, w, idx = 0 ;
scanf( " %d%d " , & N, & M);
S = 0 ;
T = N + 1 ;
memset(link, - 1 , sizeof (link));
for (i = 1 ; i <= N; i ++ ){
scanf( " %d%d " , & a, & b);
add( 0 , i, a, 0 );
add(i, N + 1 , b, 0 );
}
for (i = 1 ; i <= M; i ++ ){
scanf( " %d%d%d " , & a, & b, & w);
add(a, b, w, w);
}
dinic();
// system("pause");
return 0 ;
}