您的位置:首页 > 其它

POJ 3469 Dual Core CPU(最小割)

2013-05-15 20:32 369 查看
题意和分析转自网络http://blog.csdn.net/sdj222555/article/details/7818239

题意:有n个模块,每个模块可以运行在两个核心上,A核心和B核心,相应的有一个花费,有一些模块如果不在一个核心上运行就会产生额外的花费

现在要求最小的花费是的所有模块都运行

每个模块点,源点与其连边,容量为A花费,在用其与汇点连边,容量为相应B花费

然后如果有某对模块之间不运行在一个核心上会产生额外的花费,就对这两点建双向边,容量都为那个额外的花费

然后就是最小割模型

为啥这样建图就行呢, 可以观察, 如果一对点,假设为u,v之间不运行在一个模块会产生花费

首先,每个点不是与源点的边就是与汇点的边在割中,假如我们的割是有(s, u)  (v, t) ,那么显然(v,u)这条边必须割掉,否则 s->v->u->t构成一条路径

如果割是(s,u) (s,v) 那么u,v之间的双向边一条也不需要割掉。也就满足了题意

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define INF 0x1f1f1f
typedef struct {
int v, next, val;
} edge;
const int MAXN = 20010;
const int MAXM = 500010;
edge e[MAXM];
int p[MAXN], eid;
inline void init() {
memset(p, -1, sizeof(p));
eid = 0;
}
//有向
inline void insert1(int from, int to, int val) {
e[eid].v = to;
e[eid].val = val;
e[eid].next = p[from];
p[from] = eid++;
swap(from, to);
e[eid].v = to;
e[eid].val = 0;
e[eid].next = p[from];
p[from] = eid++;
}
//无向
inline void insert2(int from, int to, int val) {
e[eid].v = to;
e[eid].val = val;
e[eid].next = p[from];
p[from] = eid++;
swap(from, to);
e[eid].v = to;
e[eid].val = val;
e[eid].next = p[from];
p[from] = eid++;
}
int n, m; //n为点数 m为边数
int h[MAXN];
int gap[MAXN];
int source, sink;
inline int dfs(int pos, int cost) {
if (pos == sink) {
return cost;
}
int j, minh = n - 1, lv = cost, d;
for (j = p[pos]; j != -1; j = e[j].next){
int v = e[j].v, val = e[j].val;
if(val > 0){
if (h[v] + 1 == h[pos]) {
if (lv < e[j].val) d = lv;
else d = e[j].val;
d = dfs(v, d);
e[j].val -= d;
e[j ^ 1].val += d;
lv -= d;
if (h[source] >= n)return cost - lv;
if (lv == 0)break;
}
if (h[v] < minh)minh = h[v];
}
}
if (lv == cost) {
--gap[h[pos]];
if (gap[h[pos]] == 0)h[source] = n;
h[pos] = minh + 1;
++gap[h[pos]];
}
return cost - lv;
}
int sap(int st, int ed) {

source = st;
sink = ed;
int ret = 0;
memset(gap, 0, sizeof(gap));
memset(h, 0, sizeof(h));
gap[0] = n;
while (h[st] < n)ret += dfs(st, INF);
return ret;
}
int main()
{
int a,b,c,i;
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(i=1;i<=n;i++){
scanf("%d%d",&a,&b);
insert1(n+1,i,a);
insert1(i,n+2,b);
}
while(m--){
scanf("%d%d%d",&a,&b,&c);
insert2(a,b,c);
}
n=n+2;
printf("%d\n",sap(n-1,n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: