poj 3436 ACM Computer Factory 最大流拆點+輸出路徑

來源:互聯網
上載者:User

標籤:c++

題目連結:

poj3436





題意:

每台ACM 電腦包含P 個組件,當所有這些組件都準備齊全後,電腦就可以組裝了,組裝好以後就可以交給競賽隊伍使用了。電腦的生產過程是全自動的,通過N 台不同的機器來完成。每台機器從一台半成品電腦中去掉一些組件,並加入一些新的組件(去除一些組件在有的時候是必須的,因為電腦的組件不能以任意的順序組裝)。每台機器用它的效能(每小時組裝多少台電腦)、輸入/輸出規格來描述。

輸入規格描述了機器在組裝電腦時哪些組件必須準備好了。輸入規格是由P 個整數組成,每個整數代表一個組件,這些整數取值為0, 1 或2,其中0 表示該組件不應該已經準備好了,1表示該組件必須已經準備好了,2 表示該組件是否已經準備好了無關緊要。

輸出規格描述了該機器組裝的結果。輸出規格也是由P 個整數組成,每個整數取值為0 或1,其中0 代表該組件沒有生產好,1 代表該組件生產好了。

機器之間用傳輸速度非常快的流水線串連,組件在機器之間傳送所需的時間與機器生產時間相比是十分小的。

給出上述關於n台機器的描述,求一小時最多組成多少台電腦,並輸出資料流水線的路徑



解題思路:

題目已給出條件:  機器之間傳輸不需要時間,也就可以理解為流水線上每台機器的工作都是同步的,這樣就可以用網路流來解決了(單位時間問題)

解題的關鍵在於建圖.

話不多說,給出一張範例圖:

圖中紅色邊的容量應設為無窮大(單位時間運輸無限台電腦)

值得注意的是  圖中兩台機器的串連可以是雙向的(比如可以同時又B1->A2 ,B2->A1 )

關於路徑的輸出(找從n+1~2*n)開始的正向邊,有流則表示生產線經過這條路徑




代碼:

#include <iostream>#include <cstring>#include<cstdio>#define LL long long#include <queue>const int MAXN =205;const int MAXM=440020;const int INF=0x3f3f3f3f;using namespace std;struct Edge{    int from;    int to,cap,flow,next;} edge[MAXM];int head[MAXN],tot,gap[MAXN],d[MAXN],cur[MAXN],que[MAXN],p[MAXN];void init(){    tot=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int c,int f){    edge[tot]=(Edge)    {        u,v,c,f,head[u]    };    head[u] = tot++;    edge[tot]=(Edge)    {        v,u,c,c,head[v]    };    head[v] = tot++;}int isap(int source,int sink,int N){    memset(gap,0,sizeof(gap));    memset(d,0,sizeof(d));    memcpy(cur,head,sizeof(head));    int top = 0,x = source,flow = 0;    while(d[source] < N)    {        if(x == sink)        {            int Min = INF,inser=0;            for(int i = 0; i < top; ++i)            {                if(Min > edge[p[i]].cap - edge[p[i]].flow)                {                    Min = edge[p[i]].cap - edge[p[i]].flow;                    inser = i;                }            }            for(int i = 0; i < top; ++i)            {                edge[p[i]].flow += Min;                edge[p[i]^1].flow -= Min;            }            if(Min!=INF) flow += Min;            top = inser;            x = edge[p[top]^1].to;            continue;        }        int ok = 0;        for(int i = cur[x]; i != -1; i = edge[i].next)        {            int v = edge[i].to;            if(edge[i].cap > edge[i].flow && d[v]+1 == d[x])            {                ok = 1;                cur[x] = i;                p[top++] = i;                x = edge[i].to;                break;            }        }        if(!ok)        {            int Min = N;            for(int i = head[x]; i != -1; i = edge[i].next)            {                if(edge[i].cap > edge[i].flow && d[edge[i].to] < Min)                {                    Min = d[edge[i].to];                    cur[x] = i;                }            }            if(--gap[d[x]] == 0) break;            gap[d[x] = Min+1]++;            if(x != source) x = edge[p[--top]^1].to;        }    }    return flow;}int state[MAXN][2][10];int pp,n;int equall(int x,int y){    for(int i=0;i<pp;i++)        if(state[y][0][i]+state[x][1][i]==1)            return 0;    return 1;}int main(){//    freopen("in.txt","r",stdin);    int w,flag1,flag2;    while(~scanf("%d%d",&pp,&n))    {        init();        memset(state,0,sizeof(state));        for(int i=1;i<=n;i++)        {            flag1=flag2=1;            scanf("%d",&w);            for(int j=0;j<pp;j++){      //全是0或2 則串連源點                scanf("%d",&state[i][0][j]);                if(state[i][0][j]==1)                    flag1=0;            }            for(int j=0;j<pp;j++){       //全是1 則串連匯點                scanf("%d",&state[i][1][j]);                if(state[i][1][j]==0||state[i][1][j]==2)                    flag2=0;            }            addedge(i,i+n,w,0);          //拆點連自己            if(flag1==1)                addedge(0,i,INF,0);            if(flag2==1)                addedge(i+n,2*n+1,INF,0);            for(int j=1;j<i;j++){                if(equall(i,j))                    addedge(n+i,j,INF,0);                if(equall(j,i))           //注意不能是else if 兩個機器可以是雙向串連的                    addedge(n+j,i,INF,0);            }        }        printf("%d",isap(0,2*n+1,2*n+2));        int ans[400][3];        int ss=0;        for(int i=n+1;i<=(n<<1);i++)      //鄰接表找最大流中的邊            for(int j=head[i];j!=-1;j=edge[j].next)            {                if(edge[j].to==2*n+1||edge[j].to==i-n)                    continue;                if(edge[j].flow>0){                    ans[ss][0]=edge[j].from-n;                    ans[ss][1]=edge[j].to;                    ans[ss++][2]=edge[j].flow;                }            }        printf(" %d\n",ss);        for(int i=0;i<ss;i++)            printf("%d %d %d\n",ans[i][0],ans[i][1],ans[i][2]);    }    return 0;}



著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

poj 3436 ACM Computer Factory 最大流拆點+輸出路徑

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.