noi 2009 植物大战僵尸 网络流

网络流经典题

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
#define MAXN 610
#define MAXM 730000
#define INF 123456789
struct node_connect
{
    int num;
    node_connect *next;
};
struct node_dinic
{
    int u,remain;
    node_dinic *next,*inv;
};
node_dinic *graph[MAXN],epool[MAXM],*used[MAXN];
node_connect *graphs[MAXN],*grapht[MAXN],memo[MAXM];
int weight[MAXN];
int top=0,etop=0,label=0;
int n,m,S=600,T=601,ans=0;
int d[MAXN],finish[MAXN],mark[MAXN],cnt[MAXN],Q[MAXN];
bool use[MAXN];
void add1(int x,int y)
{
    node_connect *p=&memo[top++];
    p->num=y; p->next=graphs[x]; graphs[x]=p;
    p=&memo[top++];
    p->num=x; p->next=grapht[y]; grapht[y]=p;
}
void add(int x,int y,int weight)
{
    node_dinic *p=&epool[etop++],*q=&epool[etop++];
    p->u=y; p->remain=weight; p->next=graph[x]; graph[x]=p;
    q->u=x; q->remain=0; q->next=graph[y]; graph[y]=q;
    p->inv=q; q->inv=p;
}
void dfs(int i)
{
    use[i]=1;
    node_connect *p;
    for(p=graphs[i];p;p=p->next)
        if(!use[p->num])
            dfs(p->num);
    finish[top++]=i;
}
void dfst(int i)
{
    use[i]=1;
    cnt[label]++;
    mark[i]=label;
    node_connect *p;
    for(p=grapht[i];p;p=p->next)
        if(!use[p->num])
            dfst(p->num);
}
void connect()
{
    top=0;
    int i;
    memset(cnt,0,sizeof(cnt));
    memset(use,0,sizeof(use));
    for(i=0;i<n;i++)
        if(!use[i])
            dfs(i);
    memset(use,0,sizeof(use));
    for(i=n-1;i>=0;i--)
    if(!use[finish[i]])
    {
        label++;
        dfst(finish[i]);
    }
}
void reduce()
{
    top=0;
    memset(use,0,sizeof(use));
    int i;
    node_connect *p;
    for(i=0;i<n;i++)
        if(!use[i]&&cnt[mark[i]]>1)
            dfs(i);
    for(i=0;i<n;i++)
    if(!use[i])
    {
        if(weight[i]>0)
            add(S,i,weight[i]),ans+=weight[i];
        else
            add(i,T,-weight[i]);
        for(p=graphs[i];p;p=p->next)
            add(p->num,i,INF);
    }
}
bool make_level()
{
    memset(d,0xff,sizeof(d));
    int head,tail;
    Q[head=tail=1]=T;
    d[T]=0;
    while(head<=tail)
    {
        int u=Q[head++];
        used[u]=graph[u];
        for(node_dinic *p=graph[u];p;p=p->next)
        {
            int v=p->u;
            if(p->inv->remain>0&&d[v]<0)
            {
                d[v]=d[u]+1;
                Q[++tail]=v;
            }
        }
    }
    return d[S]>=0;
}
int extend(int u,int delta)
{
    int v,sum=0,temp;
    if(u==T) return delta;
    for(node_dinic *p=used[u];p;p=p->next)
    {
        used[u]=p;//重要优化 没优化之前第9个点T
        v=p->u;
        if(p->remain>0&&d[v]+1==d[u])
        {
            temp=extend(v,min(delta,p->remain));
            p->remain-=temp; p->inv->remain+=temp;
            sum+=temp;delta-=temp;
            if(delta==0)
                return sum;
        }
    }
    return sum;
}

void solve()
{
    node_connect *p;
    int i;
    connect();
    reduce();
    int ret=0;
    while(make_level())
        ret+=extend(S,INF);
    printf("%d\n",max(0,ans-ret));

}
int main()
{
    scanf("%d%d",&n,&m);
    int i,j,k,w,x,y,a,b;
    for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        {
            scanf("%d",&x);
            a=i*m+j;
            weight[a]=x;
            scanf("%d",&w);
            for(k=1;k<=w;k++)
            {
                scanf("%d%d",&x,&y);
                b=x*m+y;
                add1(a,b);
            }
            if(j<m-1)
                add1(i*m+j+1,i*m+j);
        }
    n=n*m;
    solve();
    return 0;
}

posted on 2012-07-25 22:01  myoi  阅读(342)  评论(0编辑  收藏  举报

导航