POJ 3469 Dual Core CPU【最小割】

题意: 计算机里配置了双核的CPU, 有 N 个原件, 知道了在每个原件在 每个CPU 上的 耗费,其中有 M 对原件需要协同工作,并且有协同工作的耗费,如果这些对原件是在同一个CPU上工作的话,就不计算协同工作的耗费。

分析:

        建图:

         把两个CPU 分别看成是 源点和汇点。

         从源点 到 每个顶点连接一条  容量为 AI 的边,

         从每个顶点 到 汇点 连接一条容量为 BI 的边,

         如果 两个原件具有协同工作关系,就在两个原件之间连接一条 容量为 w 的双向边。

         求出的最小割即为最小费用,  而最小割可以通过求最大流来求得。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
const int INF=0x1f1f1f1f;
const int maxn=20005;
const int maxm=800005;
struct node
{
    int c,next,to;
}e[maxm];
int tot;
int head[maxn];
void add(int s,int u,int flow)
{
    e[tot].to=u;
    e[tot].c=flow;
    e[tot].next=head[s];
    head[s]=tot++;
}
int max_flow(int st,int end,int n)
{    
    int numh[maxn],h[maxn],curedge[maxn],pre[maxn];
    int cur_flow,maxflow=0,u,tmp,neck,i;
    clr(h);   clr(numh);
    memset(pre,0xff,sizeof(pre));
    for(i=1;i<=n;i++)
        curedge[i]=head[i];
    numh[0]=n;
    u=st;
    while(h[st]<n)
    {
        if(u==end)
        {
            cur_flow=INF;
            for(i=st;i!=end;i=e[curedge[i]].to)
                if(cur_flow>e[curedge[i]].c)
                {
                    neck=i;
                    cur_flow=e[curedge[i]].c;
                }
            for(i=st;i!=end;i=e[curedge[i]].to)
            {
                tmp=curedge[i];
                e[tmp].c-=cur_flow;
                e[tmp^1].c+=cur_flow;
            }
            maxflow+=cur_flow;
            u=neck;
        }
        for(i=curedge[u];i!=-1;i=e[i].next)
            if(e[i].c&&h[u]==h[e[i].to]+1)
                break;
        if(i!=-1)
        {
            curedge[u]=i;
            pre[e[i].to]=u;
            u=e[i].to;
        }
        else 
        {
            if(--numh[h[u]]==0) break;
            curedge[u]=head[u];
            for(tmp=n,i=head[u];i!=-1;i=e[i].next)
                if(e[i].c)
                    tmp=min(tmp,h[e[i].to]);
            h[u]=tmp+1;
            ++numh[h[u]];
            if(u!=st)
                u=pre[u];
        }
    }
    return maxflow;
}
int main()
{
    int flow,a,b,w,i,n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tot=0;
        memset(head,0xff,sizeof(head));
        for(i=2;i<=n+1;i++)
        {
            scanf("%d%d",&a,&b);
            add(1,i,a);
            add(i,1,0);
            add(i,n+2,b);
            add(n+2,i,0);
        }
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&w);
            add(a+1,b+1,w);
            add(b+1,a+1,w);
        }
        flow=max_flow(1,n+2,n+2);
        printf("%d\n",flow);
    }
    return 0;
}
 

 

posted @ 2012-07-30 22:00  'wind  阅读(190)  评论(0)    收藏  举报