hdu 1569 最大点权独立集

和hdu1565很像,但此题必须用邻接表存~

用判断奇偶进行建立二分图

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define inf 99999999
using namespace std;
struct node
{
    int u,v,f;
};
node e[60000];
int map[55][55],first[2505],cc;
int next[60000],p[2505];
int a[2505];
inline void add_edge(int u,int v,int f)
{
    e[cc].u=u;
    e[cc].v=v;
    e[cc].f=f;
    next[cc]=first[u];
    first[u]=cc;
    cc++;

    e[cc].v=u;
    e[cc].u=v;
    e[cc].f=0;
    next[cc]=first[v];
    first[v]=cc;
    cc++;
}
int EK(int s,int t)
{
    queue<int> q;
    int f=0;
    while(1)
    {
        memset(a,0,sizeof(a));
        memset(p,-1,sizeof(p));
        q.push(s);
        a[s]=inf;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            int i;
            for(i=first[u];i!=-1;i=next[i])
            {
                if(!a[e[i].v]&&e[i].f)
                {
                    p[e[i].v]=i;
                    a[e[i].v]=min(a[u],e[i].f);
                    q.push(e[i].v);
                }
            }
        }
        if(a[t]==0)
            break;
        int u;
        for(u=t;u!=s;u=e[p[u]].u)
        {
            e[p[u]].f-=a[t];
            e[p[u]^1].f+=a[t];
        }
        f+=a[t];
    }
    return f;
}
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int i,j,sum=0;
        cc=0;
        memset(first,-1,sizeof(first));
        memset(next,-1,sizeof(next));
        for(i=1;i<=m;i++)
            for(j=1;j<=n;j++)
                scanf("%d",&map[i][j]),sum+=map[i][j];
        int s=0,t=n*m+1;
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=n;j++)
            {
                int tmp=(i-1)*n+j;
                if((i+j)%2==0)
                {
                    add_edge(s,tmp,map[i][j]);
                    if(i>1)
                        add_edge(tmp,(i-2)*n+j,inf);
                    if(i<m)
                        add_edge(tmp,i*n+j,inf);
                    if(j>1)
                        add_edge(tmp,(i-1)*n+j-1,inf);
                    if(j<n)
                        add_edge(tmp,(i-1)*n+j+1,inf);
                }
                else
                    add_edge(tmp,t,map[i][j]);
            }

        }
        int ans=EK(s,t);
        printf("%d\n",sum-ans);

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值