POJ 3469 Dual Core CPU(最小割)

来源:互联网 发布:linux dma 编辑:程序博客网 时间:2024/06/10 14:22

题意:

给你n个任务,每个任务要不在花费 ai 在a核上完成,要不花费 bi 在b核上完成。同时有m个约束条件,如果第i个任务和第j个任务在不同的核上完成需要额外的花费。

源点s,汇点t。
根据题意建图对于每个任务,s连i,容量为 ai
i连t,容量为 bi 。根据最小割的定义我们可以得到两个集合,一个以s为核心,一个以t为核心。现在考虑我们建的图,每个任务i的两条边中短的那条一定是最小割中的边。由此我们求出最小割即是答案。

然后我们考虑约束关系i,j,v。如果任务i和j在不同的集合中。那么建边 <i,j><j,i>,容量为v。
那么边 <i,j> 一定是最小割中的边,所以一定会算进最小割中。至此本题考虑完全,直接上isap就可以了。

#include<iostream>#include<cstdio>#include<cstring>#define inf 0x3f3f3f3ftypedef long long int lli;using namespace std;const lli maxn = 102000;struct edge{    lli to,v,next;}ed[maxn+4*200000];lli d[maxn],cur[maxn],pre[maxn],gap[maxn],q[maxn+2000],cnte,head[maxn];void ae(lli x, lli y, lli v) {    ed[cnte].to = y;    ed[cnte].v = v;    ed[cnte].next = head[x];    head[x] = cnte++;}void rbfs (lli s,lli t) {    lli fi,se;    memset(gap,0,sizeof(gap));    memset(d,-1,sizeof(d));    d[t] = 0;    gap[0] = 1;    fi = se = 0;    q[se++] = t;    while (fi != se) {        lli u = q[fi++];        for (lli i=head[u];~i;i=ed[i].next) {            lli v = ed[i].to;            if (~d[v]) continue;            d[v] = d[u] + 1;            q[se++] = v;            gap[d[v]]++;        }    }}lli isap(lli s,lli t){    memcpy(cur,head,sizeof(head));    rbfs (s,t);    lli flow = 0, u = pre[s]=s,i;    while(d[t] < t+1) {        if(u==t) {            lli f = inf,neck;            for(i= s;i != t;i = ed[cur[i]].to){                if(f > ed[cur[i]].v){                    f = ed[cur[i]].v;                    neck = i;                }            }            for(i = s;i != t;i = ed[cur[i]].to){                ed[cur[i]].v -= f;                ed[cur[i]^1].v += f;            }            flow += f;            u = neck;        }        for(i = cur[u];~i;i=ed[i].next) if(d[ed[i].to]+1 == d[u] && ed[i].v) break;        if(~i) {            cur[u] = i;            pre[ed[i].to] = u;            u = ed[i].to;        }        else{//否则回退,重新找增广路            if(0 == (--gap[d[u]])) break;//GAP间隙优化,如果出现断层,可以知道一定不会再有增广路了            lli mind = t+1;            for(i = head[u];~i;i = ed[i].next){                if(ed[i].v && mind > d[ed[i].to]){                    cur[u] = i;                    mind = d[ed[i].to];                }            }            d[u] = mind + 1;            gap[d[u]]++;            u = pre[u];        }    }    return flow;}void ini(){    memset(head,-1,sizeof(head));cnte = 0;}int main(){    int n,m,v,a,b;    scanf("%d%d",&n,&m);    ini();    int s = 0,t = n+1;    memset(head,-1,sizeof(head));cnte = 0;    for(int i = 1;i <= n;i++){        scanf("%d%d",&a,&b);        ae(s,i,a);ae(i,s,0);        ae(i,t,b);ae(t,i,0);    }    for(int i = 1;i <= m;i++){        scanf("%d%d%d",&a,&b,&v);        ae(a,b,v);ae(b,a,v);    }    printf("%lld\n",isap(s,t));    return 0;}
原创粉丝点击