hdu 3046 最大流

题意:n×m的棋盘,上面有羊和狼,可以在格子四条边上修护栏,问最少修多少护栏可以使狼吃不到羊?

分析:超级源点连狼,超级汇点连羊,容量无穷大,求最小割。

 

 

#define M 40010
struct Node{
    int c,v,next;
}E[999999];
int head[M];
int gap[M],dis[M],pre[M],cur[M],d[M];
int NE,NV;

int sap(int s,int t) {
    memset(dis,0,sizeof(int)*(NV+1));
    memset(gap,0,sizeof(int)*(NV+1));
    FOR(i,0,NV) cur[i] = head[i];
    int u = pre[s] = s, maxflow = 0;
    gap[0] = NV;    d[s]=0x7fffffff;
    while(dis[s] < NV) {
        while(1){
            for(int &i = cur[u]; i != -1; i = E[i].next) {
                int v = E[i].v;                     //cout<<u<<' '<<v<<' '<<i<<' '<<E[i].next<<endl;
                if(E[i].c && dis[u] == dis[v] + 1) {
                    d[v] = min(d[u], E[i].c);
                    pre[v] = u;
                    u = v;
                    if(v == t) {
                        int temp = s, flow = d[t];
                        maxflow += d[t];
                        for(u = pre[u];v != s;v = u,u = pre[u]) {
                            E[cur[u]].c -= flow;
                            E[cur[u]^1].c += flow;
                            d[v] -= flow;
                            if(d[v] && temp == s) temp = v;//瓶颈边的前一条边
                        }
                        u = temp;
                    }
                    break;
                }
            }
            if(cur[u] == -1) break;
        }
        if(!(--gap[ dis[u] ]))    break;
        dis[u] = NV-1;
        for(int i = head[u]; i != -1 ; i = E[i].next) {
            int v = E[i].v;
            if(E[i].c && dis[u]>dis[v]+1) {
                cur[u] = i;
                dis[u] = dis[v]+1;
            }
        }
        gap[dis[u]] ++;     u = pre[u];
    }
    return maxflow;
}


int sap1(int s,int t) {
    memset(dis,0,sizeof(int)*(NV+1));
    memset(gap,0,sizeof(int)*(NV+1));
    FOR(i,0,NV) cur[i] = head[i];
    int u = pre[s] = s,maxflow = 0,aug = -1;
    gap[0] = NV;
    while(dis[s] < NV) {
loop:        for(int &i = cur[u]; i != -1; i = E[i].next) {
            int v = E[i].v;
            if(E[i].c && dis[u] == dis[v] + 1) {
                checkmin(aug,E[i].c);
                pre[v] = u;
                u = v;
                if(v == t) {
                    maxflow += aug;
                    for(u = pre[u];v != s;v = u,u = pre[u]) {
                        E[cur[u]].c -= aug;
                        E[cur[u]^1].c += aug;
                    }
                    aug = -1;
                }
                goto loop;
            }
        }
        int mindis = NV;
        for(int i = head[u]; i != -1 ; i = E[i].next) {
            int v = E[i].v;
            if(E[i].c && mindis > dis[v]) {
                cur[u] = i;
                mindis = dis[v];
            }
        }
        if( (--gap[dis[u]]) == 0)    break;
        gap[ dis[u] = mindis+1 ] ++;
        u = pre[u];
    }
    return maxflow;
}




void Insert(int u,int v,int c,int cc ) {//形成了一些重边
    E[NE].c = c;    E[NE].v = v;
    E[NE].next = head[u];    head[u] = NE++;
    E[NE].c = cc;    E[NE].v = u;
    E[NE].next = head[v];    head[v] = NE++;
}

                                void shuchu(){
                                    cout<<E[61].next<<' '<<E[80].next<<' '<<E[78].next<<' '<<E[77].next<<endl;
                                }

int n,m;
void build(){
    int t=n*m+1;
    FOE(i,1,n)
        FOE(j,1,m){//每个格子向右边和下边建图
            int u = (i-1)*m+j;
            int v1= u+1, v2=u+m, v;
            if(j<m) Insert(u, v1, 1, 1);
            if(i<n) Insert(u, v2, 1, 1);
            scanf("%d",&v);
            if(v==1) Insert(0, u, 11111111, 11111111);
            else if(v==2) Insert(u, t, 11111111, 11111111);
        }                                                               //shuchu();
}

int main() {
     // READ
    //  WRITE
    int p=0;
    while(~scanf("%d%d",&n,&m)){
        p++;
        NV = n*m+2;
        FOR(i,0,NV) head[i] = -1;
        NE = 0;

        build();                                                        //FOR(i,0,NV)cout<<head[i];cout<<endl;

        printf("Case %d:\n%d\n",p,sap1( 0, NV-1));                       //cout<<E[61].next<<endl;
    }
}

 

posted @ 2013-06-21 13:22  心向往之  阅读(175)  评论(0编辑  收藏  举报