1. 程式人生 > >POJ3436:ACM Computer Factory(最大流)

POJ3436:ACM Computer Factory(最大流)

ACM Computer Factory

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9963   Accepted: 3738   Special Judge

題目連結:http://poj.org/problem?id=3436

Description:

As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. That is why all these computers are historically produced at the same factory.

Every ACM computer consists of P parts. When all these parts are present, the computer is ready and can be shipped to one of the numerous ACM contests.

Computer manufacturing is fully automated by using N various machines. Each machine removes some parts from a half-finished computer and adds some new parts (removing of parts is sometimes necessary as the parts cannot be added to a computer in arbitrary order). Each machine is described by its performance (measured in computers per hour), input and output specification.

Input specification describes which parts must be present in a half-finished computer for the machine to be able to operate on it. The specification is a set of P numbers 0, 1 or 2 (one number for each part), where 0 means that corresponding part must not be present, 1 — the part is required, 2 — presence of the part doesn't matter.

Output specification describes the result of the operation, and is a set of P numbers 0 or 1, where 0 means that the part is absent, 1 — the part is present.

The machines are connected by very fast production lines so that delivery time is negligibly small compared to production time.

After many years of operation the overall performance of the ACM Computer Factory became insufficient for satisfying the growing contest needs. That is why ACM directorate decided to upgrade the factory.

As different machines were installed in different time periods, they were often not optimally connected to the existing factory machines. It was noted that the easiest way to upgrade the factory is to rearrange production lines. ACM directorate decided to entrust you with solving this problem.

Input

Input file contains integers P N, then N descriptions of the machines. The description of ith machine is represented as by 2 P + 1 integers Qi Si,1 Si,2...Si,P Di,1 Di,2...Di,P, where Qi specifies performance, Si,j — input specification for part j, Di,k — output specification for part k.

Constraints

1 ≤ P ≤ 10, 1 ≤ N ≤ 50, 1 ≤ Qi ≤ 10000

Output

Output the maximum possible overall performance, then M — number of connections that must be made, then M descriptions of the connections. Each connection between machines A and B must be described by three positive numbers A B W, where W is the number of computers delivered from A to B per hour.

If several solutions exist, output any of them.

Sample Input

Sample input 1
3 4
15  0 0 0  0 1 0
10  0 0 0  0 1 1
30  0 1 2  1 1 1
3   0 2 1  1 1 1
Sample input 2
3 5
5   0 0 0  0 1 0
100 0 1 0  1 0 1
3   0 1 0  1 1 0
1   1 0 1  1 1 0
300 1 1 2  1 1 1
Sample input 3
2 2
100  0 0  1 0
200  0 1  1 1

Sample Output

Sample output 1
25 2
1 3 15
2 3 10
Sample output 2
4 5
1 3 3
3 5 3
1 2 1
2 4 1
4 5 1
Sample output 3
0 0

Hint

Bold texts appearing in the sample sections are informative and do not form part of the actual data.   題意: 這個題意難度有點大呀TnT。 簡單說就是給出n個機器,每個機器都有一個pi代表生產效率,然後後面有2*p個數,前p個代表輸入規範,後p個代表輸出規範。這裡輸入輸出規範的意思就是這臺機器可以把輸入規範轉化為輸出規範。 輸入規範裡面0就是這裡沒有零件,1就是這裡必須有零件,2就是這裡可有可不有;輸出規範裡面就只有0,1,意義同上。 現在問最多可以生產出多少臺電腦(假設機器的配合不消耗時間= =),只有輸出規範全為1的機器可以生產電腦。  

題解:

這題用最大流來做。首先建立一個超級源點和超級匯點,超級源點連上輸入規範全為0,或有0也有2的機器,因為這些機器可以“無中生有”,邊權為無窮大。

然後所有輸出規範為1的機器就連向超級匯點,畢竟此時可以生成電腦,邊權也為無窮大。

然後建立可以相互可達的機器之間的邊,這裡由於每個點有個生產效率的權值,所以我們考慮把點拆開為一條權值為其生產效率的有向邊,拆成的兩個點分別代表入讀點和出度點。這樣可以限定一條生產線上的生產效率。

然後直接跑最大流就好了~

最後統計結果的時候就隨便統計一下就好了...畢竟special judge。如果一個出度點到一個入讀點的邊上面有流量,就代表了兩個點之間有合作關係,就輸出這兩個點。

 

程式碼如下:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#define INF 99999999
using namespace std;

const int N = 150;
int P,n,tot;
int p[N],m[N][N],head[N],cur[N],d[N];

struct Edge{
    int u,v,c,flow,next;
}e[N<<1];
void adde(int u,int v,int w,int f){
    e[tot].v=v;e[tot].u=u;e[tot].c=w;e[tot].flow=f;
    e[tot].next=head[u];head[u]=tot++;
}
bool bfs(int s,int t){
    for(int i=0;i<=2*n+2;i++) d[i]=0;d[s]=1;
    queue <int > q;q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(!d[v] && e[i].c>e[i].flow){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[t]!=0;
}
int dfs(int s,int a){
    if(s==2*n+1 || a==0) return a;
    int flow = 0;
    for(int &i=cur[s];i!=-1;i=e[i].next){
        int v=e[i].v,f;
        if(d[v]!=d[s]+1) continue ;
        f=dfs(v,min(a,e[i].c-e[i].flow));
        if(f){
            e[i].flow+=f;
            e[i^1].flow-=f;
            a-=f;
            flow+=f;
            if(a==0) break;
        }
    }
    if(!flow) d[s]=-1;
    return flow;
}
int main(){
    scanf("%d%d",&P,&n);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++){
        scanf("%d",&p[i]);
        for(int j=1;j<=2*P;j++) scanf("%d",&m[i][j]);
    }

    for(int i=1;i<=n;i++){
        adde(i,i+n,p[i],0);
        adde(i+n,i,0,0);
        int flag1=1,flag2=1;
        for(int j=1;j<=P;j++){
            if(m[i][j]==1) flag1=0;
            if(m[i][j+P]!=1) flag2=0;
        }
        if(flag1) adde(0,i,INF,0),adde(i,0,0,0);
        if(flag2) adde(i+n,2*n+1,INF,0),adde(2*n+1,i+n,0,0);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue ;
            bool ok = true ;
            for(int k=P+1;k<=P*2;k++){
                int now = k-P;
                if(m[j][now]==2) continue ;
                if(m[i][k]!=m[j][now]) ok=false;
            }
            if(ok){
                adde(i+n,j,INF,0);
                adde(j,i+n,0,0);
            }
        }
    }

    int max_flow = 0;
    while(bfs(0,2*n+1)){
        for(int i=0;i<=2*n+1;i++) cur[i]=head[i];
        max_flow+=dfs(0,INF);
    }
    printf("%d ",max_flow);
    int tot=0;
    vector <pair<int,int> > ans[N];
    for(int i=1+n;i<=2*n;i++){
        for(int j=head[i];j!=-1;j=e[j].next){
            int v=e[j].v;
            if(v!=2*n+1 && v!=0 && e[j].flow && v!=i-n) ans[i-n].push_back(make_pair(v,e[j].flow)),tot++;
        }
    }
    printf("%d\n",tot);
    for(int i=1;i<=n;i++)
        for(int j=0;j<ans[i].size();j++){
            printf("%d %d %d\n",i,ans[i][j].first,ans[i][j].second);
        }
    return 0;
}