码迷,mamicode.com
首页 > 其他好文 > 详细

「网络流24题」 9. 方格取数问题

时间:2018-01-03 19:48:04      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:main   const   cst   size   ini   algo   最大点权独立集   block   printf   

「网络流24题」 9. 方格取数问题

<题目链接>


二分图的最大点权独立集

建立二分图,使得每个点与其相邻的点在不同的部。

源向X部引有向边,Y部向汇引有向边,边权为点权。

X部每个点到其相邻的点引有向边,边权INF,这个边的两个断电不能同时被选。

那么S-X-Y-T的任意一条增广路都表示选了两个相邻的点。

于是问题转化为求网络最小割。

最终的答案为所有点的点权和(先都选上)减去网络最小割(不能选的最小点权集)。

#include <algorithm>
#include <climits>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN=10010,MAXM=59610;
int m,n,S,T,cnt,ans,head[MAXN],cur[MAXN],dis[MAXN];
struct edge
{
    int nxt,to,w;
}e[MAXM];
void AddEdge(int x,int y,int w)
{
    e[++cnt].nxt=head[x];
    e[cnt].to=y;
    e[cnt].w=w;
    head[x]=cnt;
}
void AddEdges(int x,int y,int w)
{
    AddEdge(x,y,w);
    AddEdge(y,x,0);
}
int num(int i,int j)
{
    return (i-1)*n+j;
}
void Init(int i,int j)
{
    int w,t=num(i,j);
    scanf("%d",&w);
    ans+=w;
    if(i+j&1)
        AddEdges(t,T,w);
    else
    {
        AddEdges(S,t,w);
        if(i>1)
            AddEdges(t,t-n,INT_MAX);
        if(i<m)
            AddEdges(t,t+n,INT_MAX);
        if(j>1)
            AddEdges(t,t-1,INT_MAX);
        if(j<n)
            AddEdges(t,t+1,INT_MAX);
    }
}
bool BFS(void)
{
    queue<int> q;
    memset(dis,0,sizeof dis);
    q.push(S);
    dis[S]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x],t;i;i=e[i].nxt)
            if(e[i].w && !dis[t=e[i].to])
            {
                q.push(t);
                dis[t]=dis[x]+1;
            }
    }
    return dis[T];
}
int DFS(int x,int k)
{
    if(x==T || !k)
        return k;
    int tmp=0;
    for(int i=cur[x],t,flow;i;i=e[i].nxt)
        if(e[i].w && dis[t=e[i].to]==dis[x]+1 && (flow=DFS(t,min(k,e[i].w))))
        {
            cur[x]=i;
            e[i].w-=flow;
            e[((i-1)^1)+1].w+=flow;
            k-=flow;
            tmp+=flow;
        }
    if(!tmp)
        dis[x]=0;
    return tmp;
}
void Dinic(void)
{
    int flow;
    while(BFS())
        while(memcpy(cur,head,sizeof cur),flow=DFS(S,INT_MAX))
            ans-=flow;
}
int main(int argc,char *argv[])
{
    scanf("%d %d",&m,&n);
    T=m*n+1;
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            Init(i,j);
    Dinic();
    printf("%d",ans);
    return 0;
}

谢谢阅读

「网络流24题」 9. 方格取数问题

标签:main   const   cst   size   ini   algo   最大点权独立集   block   printf   

原文地址:https://www.cnblogs.com/Capella/p/8185107.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!