zoukankan      html  css  js  c++  java
  • 网络流最小割 王者之剑

      传送门

        不用考虑走的方法,因为一旦合法,即不同时取相邻的两个,一定能达到。

        所以只用考虑怎么取就行了。

        把棋盘黑白染色,S到黑点建权值为val的边,白点到T建权值为val的边,

        然后把相邻的黑白点建一条为inf的边。

        求最小割。

        不得不提一句:边从零开始建和从一开始建一个wa一个a。。

                                  ^时相应的正边和反边必须对应。(卡了好久,身败名裂

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #define inf 100000000
    using namespace std;
    int n,m,a[505][505],b[505][505],S=0,T,cnt,c[505][505];
    int dep[100005],e,adj[100005],sum=0;
    struct node
    {
    	int v,l,next;
    } lu[100005];
    void add(int u,int v,int l)
    {lu[e].v=v;lu[e].l=l;lu[e].next=adj[u];adj[u]=e++;}
    inline int bfs()
    {
    	memset(dep,0,sizeof(dep));
    	queue<int> q;
    	dep[S]=1;
    	q.push(S);
    	while(!q.empty())
    	{
    	    int x=q.front();q.pop();
    	    for(int i=adj[x];i!=-1;i=lu[i].next)
    	    {
    	    	 int to=lu[i].v; 
    	         if(lu[i].l&&!dep[to])
    	         {
    	         	  dep[to]=dep[x]+1;
    	         	  q.push(to);
    	         	  if(to==T)return 1;
    			 }
    		}
    	}
    	return 0;
    }
    inline int read()
    {
        int su=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch<='9'&&ch>='0'){su=su*10+ch-'0';ch=getchar();}     
        return su;
    }
    inline int dfs(int now,int f){
    	if(now==T){
    		return f;
    	}
    	int tmp=f;
    	for(int i=adj[now];i!=-1;i=lu[i].next){
    		int to=lu[i].v,w=lu[i].l;
    		if(w&&tmp&&dep[to]==dep[now]+1){
    			int k=dfs(to,min(w,tmp));
    			if(!k){
    				dep[to]=0;
    				continue;
    			}
    			lu[i].l-=k;
    			lu[i^1].l+=k;
    			tmp-=k;
    		}
    	}
    	return f-tmp;
    }
    int yjn()
    {
        freopen("Excalibur.in","r",stdin);
        freopen("Excalibur.out","w",stdout);
      	scanf("%d%d",&n,&m);
    	memset(adj,-1,sizeof(adj));
    	for(int i=1;i<=n;i++)
    	{
    	   int k=0;
    	   if(i&1)k=1;
    	   for(int j=1;j<=m;j++)
    	   {
    	   	  a[i][j]=++cnt;
    		  b[i][j]=k;k^=1;
    	      c[i][j]=read();
    	      sum+=c[i][j];
    		}
    	}
    /*	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		   cout<<b[i][j]<<" ";
    		cout<<endl;
    	}*/
    	T=cnt+3;
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
    	  {
    		if(b[i][j])
    		  {add(a[i][j],T,c[i][j]),add(T,a[i][j],0);}
    		else
    		  {add(S,a[i][j],c[i][j]),add(a[i][j],S,0);}
          }
    	for(int i=1;i<=n;i++)
    	   for(int j=1;j<=m;j++)
    	   {
    	   	    if(b[i][j]==0)
    	   	    {
    	   	    	if(i!=1){add(a[i][j],a[i-1][j],inf),add(a[i-1][j],a[i][j],0);}
    	   	    	if(i!=n){add(a[i][j],a[i+1][j],inf),add(a[i+1][j],a[i][j],0);}
    	   	    	if(j!=1){add(a[i][j],a[i][j-1],inf),add(a[i][j-1],a[i][j],0);}
    				if(j!=m){add(a[i][j],a[i][j+1],inf),add(a[i][j+1],a[i][j],0);}
    			}
    	   }
    	int ans=0;
    	while(bfs())
    	    ans+=dfs(S,inf);
    	cout<<(sum-ans);
    }
    int qty=yjn();
    int main(){;}

  • 相关阅读:
    正则表达式30分钟入门教程
    解读C#中的正则表达式1
    web开发技巧经验积累
    常用效果的实现(Javascript的子父页访问、函数调用)
    document.execCommand()编程
    把任意文件隐藏在一张图片里
    在C#中如何实现Form与Form之间的通信
    全国各个省市数据库
    对长时间装载的ASP.NET页如何在客户端浏览器中显进度
    关于UPC E条码的校验
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632762.html
Copyright © 2011-2022 走看看