網路流+拆點+sap+uva10330

u010660276發表於2014-01-15

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=210;
const int INF=0x3f3f3f3f;
struct node
{
    int v,next,f;
} edge[maxn*maxn];
int pre[maxn],cur[maxn],gap[maxn],head[maxn],dis[maxn];
int N,M,num,B,D,nn;
void init()
{
    num=0;
    memset(head,-1,sizeof(head));
}
void add_edge(int a,int b,int x)
{
    edge[num].v=b;
    edge[num].next=head[a];
    edge[num].f=x;
    head[a]=num++;
    edge[num].v=a;
    edge[num].next=head[b];
    edge[num].f=0;
    head[b]=num++;
}
int SAP(int s,int t)
{
    for(int i=0; i<=nn; i++)
    {
        cur[i]=head[i];
        gap[i]=dis[i]=0;
    }
    int u;
    int flow=0,aug=INF;
    gap[s]=nn;
    u=pre[s]=s;
    bool flag;
    while(dis[s]<nn)
    {
        flag=0;
        for(int &j=cur[u]; j!=-1; j=edge[j].next)
        {
            int v=edge[j].v;
            if(edge[j].f>0&&dis[u]==dis[v]+1)
            {
                flag=1;
                if(edge[j].f<aug)
                    aug=edge[j].f;
                pre[v]=u;
                u=v;
                if(u==t)
                {
                    flow+=aug;
                    while(u!=s)
                    {
                        u=pre[u];
                        edge[cur[u]].f-=aug;
                        edge[cur[u]^1].f+=aug;
                    }
                    aug=INF;
                }
                break;
            }
        }
        if(flag) continue;
        int mindis=nn;
        for(int j=head[u];j!=-1;j=edge[j].next)
        {
            int v=edge[j].v;
            if(dis[v]<mindis&&edge[j].f>0)
            {
                mindis=dis[v];
                cur[u]=j;
            }
        }
        if((--gap[dis[u]])==0)
        break;
        gap[dis[u]=mindis+1]++;
        u=pre[u];
    }
    return flow;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif

    int a,b,x;
    while(cin>>N)
    {
        init();
        for(int i=1; i<=N; i++)
        {
            cin>>x;
            add_edge(i,i+N,x);
        }
        cin>>M;
        for(int i=0; i<M; i++)
        {
            cin>>a>>b>>x;
            add_edge(a+N,b,x);
        }
        cin>>B>>D;
        for(int i=1; i<=B; i++)
        {
            cin>>a;
            add_edge(0,a,INF);
        }
        for(int i=1; i<=D; i++)
        {
            cin>>a;
            add_edge(a+N,2*N+1,INF);
        }
        nn=2*(N+1);
        cout<<SAP(0,2*N+1)<<endl;
    }
    return 0;
}

下面是EK

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<string>
#include<cmath>
#include<fstream>
#include<iomanip>

using namespace std;

#define MAX_INT 0x7fffffff
#define MAX_LL 0x7fffffffffffffff
#define ULL unsigned long long
#define LL long long
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))

#define MAXN 222
#define MAXM 22222
#define INF (MAX_INT>>1)

int cap[MAXN][MAXN];
int n,m,b,d;
int flow[MAXN][MAXN];
int p[MAXN];

queue<int> q;
int Edmonds_Karp(int s, int t){
    int a[MAXN],f=0;
    memset(flow,0,sizeof(flow));        //從0開始
    while(!q.empty()) q.pop();
    while(1){
        memset(a,0,sizeof(a));
        a[s]=INF;   q.push(s);          //000
        while(!q.empty()){              //BFS
            int u=q.front();    q.pop();
            for(int v=0; v<=n; v++) if(!a[v] && cap[u][v]>flow[u][v]){
                a[v]=MIN(a[u],cap[u][v]-flow[u][v]);       //更新,還不特別清楚。。。
                p[v]=u; q.push(v);
            }
        }
        if(!a[t]) break;
        for(int v=t; v!=s; v=p[v]){
            flow[p[v]][v]+=a[t];        //更新當前流量
            flow[v][p[v]]-=a[t];
        }
        f+=a[t];
    }
    return f;
}

int main(){
    //freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);

    while(scanf(" %d",&n)==1){
        int i,j,t2,t1,w_;
        memset(cap,0,sizeof(cap));      //拆點,把點i拆成i、n+i
        for(i=1; i<=n; i++) scanf(" %d",&cap[i][n+i]);

        scanf(" %d",&m);
        for(i=1; i<=m; i++){
            scanf(" %d %d %d",&t1,&t2,&w_);
            cap[n+t1][t2]=w_;           //注意弧的始終點
        }
        scanf(" %d %d",&b,&d);
        for(i=1; i<=b; i++){
            scanf(" %d",&t1);
            cap[0][t1]=INF;
        }
        for(i=1; i<=d; i++){
            scanf(" %d",&t1);
            cap[t1+n][2*n+1]=INF;
        }
        n=n*2+1;
        cout<<Edmonds_Karp(0,n)<<endl;
    }

    return 0;
}



相關文章