POJ_3469 Dual Core CPU 最大流

来源:互联网 发布:酒店智能门锁 网络 编辑:程序博客网 时间:2024/06/05 10:15

http://poj.org/problem?id=3469

题意:

有N项工作需要用CPU执行完成,现在只有2个CPU,已知每个项任务在两个CPU上

的执行时间,并且还给出了一些约束条件,每个约束条件是:(u , v  , c)表示如果任务

u和v不在同一个机器上执行的话,就需要付出额外的c的代价,求完全任务的最少花

费是多少。

思路:

首先每项任务都需要完成,而且每项任务都只能在一台机器上完成,这不免会让人想

到是否可以用2-sat,但是问题是题目中并没有给没有给出两个不能在同一台机器上, 

而是给出了两个任务不在同一台机器上的代价,没有“冲突”,因此我们不能用2-sat解决。

然后就是考虑到每个任务只要在A机器或是B机器上完成,也就是说我们只需要确定一种

方案将所有任务分别分在A或是B上就可以了,这样我们就会想到最大流最小割定理,可

以利用求最大流来求出图的最小割,从而求解本题。建图的原则是,引入一个超级源点

和超级汇点,从源点引一条边到每个点,代价为该点在机器A上执行的时间,从每个点引

一条边到汇点,代价为该点在机器B上执行的时间,对于题目中给出的约束(u , v ,c )添加

一条总u到v的代价为c的边和 v到u的代价为c的边,最后跑一次最大流的sap算法就可以出解。


代码:

#include<stdio.h>#include<string.h>#define MIN(a,b) (a)>(b)?(b):(a)#define CC(m ,what) memset(m , (what) , sizeof(m))#define FF(i , CH) for(int i=0;i<CH;i++)int N ,M ,S,T;const int MAX_E = 600000 ;const int MAXN = 20020 ;const int inf = (1<<30) ;struct Node{    int num ,dis ,next;}p[MAX_E*2] ;int root[MAXN] ,cnt,nodenum;void init(){    memset(root, -1 , sizeof(root));    cnt = 0 ; S = 0 ; T = N + 1 ;}void add(int a , int b , int c ,int cc=0){    p[cnt].num = b ;    p[cnt].dis = c ;    p[cnt].next = root[a] ;    root[a] = cnt++ ;    p[cnt].num = a ;    p[cnt].dis = cc ;    p[cnt].next = root[b] ;    root[b] = cnt++ ;}int dis[MAXN] , gap[MAXN] , cur[MAXN] , pre[MAXN];/*用领接矩阵实现的SAPdis[i]: 层次图中点i到T的距离cur[i]: i结点当前出去的边的编号pre[i]: i结点的前一个结点*/void checkmin(int &a , int b){    a = a > b ? b : a ;}void sap(){    CC(dis,  0); CC(gap , 0) ;    FF(i , nodenum)     cur[i] = root[i] ;    int u = pre[S] = S ,max_flow = 0 , aug = inf ;    gap[0] = nodenum ;    while( dis[S] < nodenum){loop :            for(int &i=cur[u] ;i!=-1;i=p[i].next){                int v = p[i].num ;                if( p[i].dis && dis[u] == dis[v] + 1){                        checkmin( aug , p[i].dis ) ;                        pre[ v ] = u ; u = v ;                        if(v == T){                                max_flow += aug ;                                for(u = pre[u] ; v != S ; v=u,u=pre[u]){                                    p[ cur[u] ].dis -= aug ;                                    p[ cur[u]^1 ].dis += aug ;                                }                                aug = inf ;                        }                        goto loop ;                }            }            int mind = nodenum  ;            for(int i=root[u] ;i!=-1;i=p[i].next){                int v = p[i].num ;                if( p[i].dis && mind > dis[v] ){                    mind = dis[v] ;                    cur[u] = i ;                }            }            if( (--gap[ dis[u] ])==0)   break ;            gap[ dis[u] = mind + 1 ]++ ;            u = pre[u] ;    }    printf("%d\n",max_flow) ;}int main(){    int a, b ,c;    while(scanf("%d%d",&N,&M) == 2){        init() ;        for(int i=1;i<=N;i++){            scanf("%d%d",&a,&b);            add(S,i,a); add(i,T,b);        }        for(int i=1;i<=M;i++){            scanf("%d%d%d",&a,&b,&c);            add(a,b,c,c) ;        }        nodenum = N + 2 ;        sap() ;    }    return 0;}


原创粉丝点击