poj 1149 最大流构图

基本规律:

规律1. 如果几个结点的流量的来源完全相同,则可以把它们合并成一个。
规律2. 如果几个结点的流量的去向完全相同,则可以把它们合并成一个。
规律3. 如果从点u到点v有一条容量为∞的边,并且点v除了点u以外没有别的流量来源,则可以把这两个结点合并成一个。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn = 205;
const int INF = 0x3f3f3f3f;

int cap[maxn][maxn];
int flow[maxn][maxn];
int ansf;
int n;
int s,t;

void EK(){
    ansf = 0;
    int p[maxn];
    memset(flow,0,sizeof(flow));
    queue<int> Q;
    while(!Q.empty())  Q.pop();
    int res[maxn];
    while(true){
        memset(p,0,sizeof(p));
        p[s] = s;
           memset(res,0,sizeof(res));
        res[s] = INF;
        Q.push(s);    
         while(!Q.empty()){
             int u = Q.front();  Q.pop();
            for(int v=1;v<=n+1;v++){
                if(!res[v] && cap[u][v] > flow[u][v]){
                     p[v] = u;
                     Q.push(v);
                     res[v] = min(res[u],cap[u][v] - flow[u][v]); //printf("%d %d\n",u,res[v]);
              }
           }    
       }    //printf("***  %d\n",res[t]);
       if(res[t] == 0)  break;
       for(int i=t;i!=s;i=p[i]){
           flow[p[i]][i] += res[t];  
           flow[i][p[i]] -= res[t];
        }
        ansf += res[t];  //printf("HH**  %d\n",ansf);
     }
     return;
}
int main()
{
    //if(freopen("input.txt","r",stdin)== NULL)  {printf("Error\n"); exit(0);}
    int N,M,A;
    cin>>M>>N;
    s = 0; t = N+1;
    n = N ;
    memset(cap,0,sizeof(cap));    
    int c[1005];
    for(int i=1;i<=M;i++){
        cin>>c[i]; 
    }
    
    int d[maxn];
    int a[1005];
    memset(a,0,sizeof(a));
    for(int i=1;i<=N;i++){
        cin>>A;
        for(int j=1;j<=A;j++){
            int b; 
            cin>>b;
            if(!a[b]){
                 cap[s][i] += c[b];
                 a[b] = i;
            } 
            else{
                 cap[a[b]][i] = INF;
                 a[b] = i;
            }
        }
        cin>>d[i];
    }  
    for(int i=1;i<=N;i++){
        cap[i][t] = d[i];           
    }  
        EK();
        printf("%d\n",ansf);           
    return 0;
}
原文地址:https://www.cnblogs.com/acmdeweilai/p/3103502.html