POJ 3436 ACM Computer Factory(拆点+前向星dinic)||(拆点+邻接矩阵dinic)||(不拆点+dinic))

来源:互联网 发布:领航者软件lhzsoft 编辑:程序博客网 时间:2024/04/28 22:15

题目大意:就是第一行两个数p,n分别代表电脑零件的个数,和有多少机器。接下来的n行每行2*p+1个数,第一个数为机器工作的效率,其余代表机器加工前和后电脑的变化,求机器一起工作的最大效率,并输出路径。


思路:由于源点的流入和普通链接点的流入,可能会大于当前点的容量,因此拆点.那么,怎么再判断有多少个机器用到了呢,这就要原来机器的工作效率,和剩余网络,如果原来的工作效率大于剩余网络那么一定该机器被用到了既有流。(注意建图时后来加源和汇,且机器和机器相连的时候应该注意到分开,因此就要相应的加上m值,但是应该加到i,j谁的值上,答案是i上因为如果加到j上相应的遍历的时候要减去m(Q[j].to-m)因为有逆向建图,所以在以a为下一个链接点时可能出现负值在vv[][]数组中 。

法一:前向星



#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<queue>#include<algorithm>#define MAX 1000#define inf 0x3f3f3f3fusing namespace std;struct node{    int w,in[52],out[52];}q[100];struct no{    int to,w,next;}Q[100000];int s,e,cnt,l[51100],qu[50000],head[50000];int vv[1100][1100];void bu(int a,int b,int c){    Q[cnt].to=b;    Q[cnt].w=c;    Q[cnt].next=head[a];    head[a]=cnt++;    Q[cnt].to=a;    Q[cnt].w=0;    Q[cnt].next=head[b];    head[b]=cnt++;}int bfs(){    memset(l,-1,sizeof(l));    l[s]=0;    queue<int>qu;    while(!qu.empty())        qu.pop();    qu.push(s);    while(!qu.empty()){        int v=qu.front();        qu.pop();        for(int i=head[v];~i;i=Q[i].next){            if( l[Q[i].to ]==-1&&Q[i].w>0 ){                l[Q[i].to ]=l[v]+1;                qu.push(Q[i].to);            }        }    }    return l[e]!=-1;}int dfs(int x,int f){    if(x==e||!f) return f;    int tmp=0,a;    for(int i=head[x];~i;i=Q[i].next){        if(l[x]+1==l[Q[i].to ]&&Q[i].w>0 ){            a=dfs(Q[i].to,min(Q[i].w,f-tmp));            if(a>0){                Q[i].w-=a;                Q[i^1].w+=a;                tmp+=a;                if(tmp==inf)break;            }        }    }    if(!tmp) l[x]=-1;    return tmp;}int main(){    int n,m,j,i,k;    while(~scanf("%d%d",&n,&m)){        cnt=0;        memset(vv,0,sizeof(vv));        memset(head,-1,sizeof(head));        s=0,e=2*m+1;        for(i=1;i<=m;i++){            int bj=false;            scanf("%d",&q[i].w);            bu(i,i+m,q[i].w);///***一般源和汇都是后来的时候才链接            for(j=0;j<n;j++){                scanf("%d",&q[i].in[j]);                 if(q[i].in[j]==1){                    bj=true;                }            }            if(!bj)                bu(0,i,q[i].w);            bj=false;            for(j=0;j<n;j++){                scanf("%d",&q[i].out[j]);                if(q[i].out[j]!=1){                    bj=true;                }            }            if(!bj)                bu(i+m,2*m+1,q[i].w);        }        for(i=1;i<=m;i++){            for(j=1;j<=m;j++){                if(i==j)continue;                bool vis=false;                for(k=0;k<n;k++){                    if( (q[i].out[k]!=q[j].in[k])&&q[j].in[k]!=2){                        vis=true;break;                    }                }                if(!vis){                    bu( i+m,j,q[i].w);///****                    vv[m+i][j]=1;                }            }        }        int ans=0;        while(bfs()){            ans+=dfs(s,inf);        }        int sum=0;        for(i=1;i<=m;i++){///*********            for(j=head[i+m];j!=-1;j=Q[j].next){                if( vv[i+m][Q[j].to ]&&Q[j].w<q[i].w ){                    sum++;                }            }        }        printf("%d %d\n",ans,sum);        for(i=1;i<=m;i++){            for(j=head[i+m];~j;j=Q[j].next){                if(vv[i+m][Q[j].to]&&Q[j].w<q[i].w){                    printf("%d %d %d\n",i,Q[j].to,q[i].w-Q[j].w);                }            }        }    }}

法二:邻接矩阵+拆点dinic


#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<queue>#include<algorithm>#define MAX 1000#define inf 0x3f3f3f3fusing namespace std;struct node{    int w,in[52],out[52];}q[100];int Map[1100][1100],s,e,l[1100];int flow[1100][1100];int bfs(){    memset(l,-1,sizeof(l));    l[s]=0;    queue<int>Q;    while(!Q.empty())        Q.pop();    Q.push(s);    while(!Q.empty()){        int v=Q.front();        Q.pop();        for(int i=0;i<=e;i++){            if(Map[v][i]&&l[i]==-1){                l[i]=l[v]+1;                Q.push(i);            }        }    }    return l[e]!=-1;}int dfs(int x,int f){    if(x==e||!f){        return f;    }    int tmp=0,a;    for(int i=0;i<=e;i++){        if(l[i]==l[x]+1&&Map[x][i]){            a=dfs(i,min(Map[x][i],f-tmp));            if(a>0){                Map[x][i]-=a;                Map[i][x]+=a;                flow[x][i]+=a;                flow[i][x]-=a;                tmp+=a;                if(tmp==f)break;            }        }    }    if(!tmp)l[x]=-1;    return tmp;}int main(){    int n,m,i,j,k;    while(~scanf("%d%d",&n,&m)){        memset(flow,0,sizeof(flow));        s=0,e=2*m+1;        memset(Map,0,sizeof(Map));        for(i=1;i<=m;i++){            scanf("%d",&q[i].w);            for(j=0;j<n;j++){                scanf("%d",&q[i].in[j]);            }            for(j=0;j<n;j++){                scanf("%d",&q[i].out[j]);            }        }        bool bj;        for(i=1;i<=m;i++){            for(j=1;j<=m;j++){                if(i!=j){                    bj=false;                    for(k=0;k<n;k++){                        if( (q[i].out[k]!=q[j].in[k])&&q[j].in[k]!=2){                            bj=true;break;                        }                    }                    if(!bj){                        Map[i+m][j]=q[i].w;///**                    }                }            }        }        for(i=1;i<=m;i++){            Map[i][i+m]=q[i].w;            bj=false;            for(j=0;j<n;j++){                if(q[i].in[j]==1){                    bj=true;break;                }            }            if(!bj){                Map[0][i]=q[i].w;            }            bj=false;            for(j=0;j<n;j++){                if(q[i].out[j]!=1){                    bj=true;break;                }            }            if(!bj)                Map[i+m][2*m+1]=q[i].w;        }        int ans=0;        while(bfs()){            ans+=dfs(0,inf);        }        printf("%d ",ans);        int sum=0;        for(i=1;i<=e;i++){            for(j=1;j<=i;j++){                if(flow[i][j]>0)                    sum++;            }        }        printf("%d\n",sum);        for(i=1;i<=e;i++){            for(j=1;j<=i;j++){                if(flow[i][j]>0)                    printf("%d %d %d\n",i-m,j,flow[i][j]);            }        }    }    return 0;}
法三:邻接矩阵不拆点(可能题目水了,不拆点也可以过,直接将上边代码的源点汇点和相邻的中间点去掉相应的m即可。)

1 0
原创粉丝点击