zoukankan      html  css  js  c++  java
  • 「网络流24题」 9. 方格取数问题

    「网络流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;
    }
    

    谢谢阅读

  • 相关阅读:
    shell、cmd、dos和脚本语言杂谈(转)
    windows命令之PING DIR DEL CD TASKLIST (转)
    STM32的操作过程,寄存器配置与调试过程(转载)
    关于MCU的烧录,下载与其他接口的比较(一)
    关于Spring Security 3获取用户信息的问题
    Spring security 获取当前用户
    Spring Security3实现,权限动态获取
    Spring Security教程
    spring security 3 自定义认证,授权示例
    SpringSecurity自定义过滤器
  • 原文地址:https://www.cnblogs.com/Capella/p/8185107.html
Copyright © 2011-2022 走看看