zoukankan      html  css  js  c++  java
  • [bzoj1324]Exca王者之剑_最小割

    Exca王者之剑 bzoj-1324

    题目大意题目链接

    注释:略。


    想法

    最小割经典模型。

    所有格子向源点连权值为格子权值的边。

    将棋盘黑白染色后白点反转源汇。

    如果两个格子相邻那么黑点向白点连$inf$的有向边。

    求最小割即可。

    开始把所有点的权值都加上,如果被割掉那么就表示这个格子不选。

    Code

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f 
    #define N 100010 
    using namespace std;
    queue<int>q;
    int to[N<<1],nxt[N<<1],tot=1,val[N<<1],head[N],dis[N],S,T;
    int d1[]={-1,1,0,0};
    int d2[]={0,0,1,-1};
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
    inline void add(int x,int y,int z)
    {
    	to[++tot]=y; val[tot]=z; nxt[tot]=head[x]; head[x]=tot;
    	to[++tot]=x; val[tot]=0; nxt[tot]=head[y]; head[y]=tot;
    }
    bool bfs()
    {
    	memset(dis,-1,sizeof dis); while(!q.empty()) q.pop();
    	dis[S]=0; q.push(S); while(!q.empty())
    	{
    		int x=q.front(); q.pop(); for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]==-1&&val[i]>0)
    		{
    			dis[to[i]]=dis[x]+1; q.push(to[i]);
    			if(to[i]==T) return true;
    		}
    	}
    	return false;
    }
    int dinic(int x,int fl)
    {
    	int tmp=fl; if(x==T) return fl; for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]==dis[x]+1&&val[i]>0)
    	{
    		int mdl=dinic(to[i],min(val[i],tmp));
    		if(!mdl) dis[to[i]]=-1;
    		tmp-=mdl; val[i]-=mdl; val[i^1]+=mdl;
    		if(!tmp) break;
    	}
    	return fl-tmp;
    }
    int main()
    {
    	int ans=0;
    	int n=rd(),m=rd(); T=n*m+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    	{
    		int v=rd(); ans+=v;
    		if((i+j)&1) add(S,(i-1)*m+j,v),add((i-1)*m+j,T,0);
    		else add((i-1)*m+j,T,v),add(S,(i-1)*m+j,0);
    		for(int k=0;k<4;k++)
    		{
    			int x=i+d1[k],y=j+d2[k];
    			if(x>=1&&x<=n&&y>=1&&y<=m) ((i+j)&1)?
    			(add((i-1)*m+j,(x-1)*m+y,inf)):
    			(add((x-1)*m+y,(i-1)*m+j,inf));
    		}
    	}
    	while(bfs()) ans-=dinic(S,1<<30);
    	cout << ans << endl ;
    	return 0;
    }
    

    小结:最小割的建模还是比较具有规律性的。

  • 相关阅读:
    [leetcode]49. Group Anagrams变位词归类
    [leetcode]40. Combination Sum II组合之和(每元素限用一次)
    [leetcode]39. Combination Sum组合之和
    [leetcode]35. Search Insert Position寻找插入位置
    [leetcode]28. Implement strStr()实现strStr()
    [leetcode]25. Reverse Nodes in k-Group每k个节点反转一下
    [leetcode]24. Swap Nodes in Pairs交换节点对
    SVG基础知识 Adobe Illustrator绘制SVG
    Java静态方法和实例方法 java中的数组作为形参传入
    SVG可伸缩的矢量图形
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10244113.html
Copyright © 2011-2022 走看看