zoukankan      html  css  js  c++  java
  • Luogu5038 SCOI2012奇怪的游戏

    Description

    link

    Solution

    发现这个棋盘和操作构成了一个二分图……

    我们把整个棋盘分为两个部分

    然后每次操作会改变黑点白点上的两个值

    设点的个数和权值和分别为 (num)(sum)

    讨论一发:

    (1.) 个数相同

    先判断 (sum) 是不是一样

    考虑到黑点白点个数有一样,如果有一个值 (x) 是经过操作所有点都可以达到的

    就是点的终值为 (x)

    那么 (x+1) 也可以被达到

    那么如果 (x) 不行,(x-1) 也不行

    那么我们求出一个 (x) 或者证明不存在即可

    这个过程因为数大了可能会存在(存在“解的单调性”),所以二分一下

    然后类多重匹配用最大流做

    (2.) 个数不同

    设终值为 (p)

    有:

    [x imes num_1-sum_1=x imes num_2-sum_2 ]

    推一下:

    [x=frac{sum_1-sum_2}{num_1-num_2} ]

    但是这个 (x) 不一定可行,建个图判断一下吧

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=2010,M=2e5+10;
    	struct node{
    		int to,lim,nxt;
    	}e[M<<1];
    	inline int max(int x,int y){return x<y?y:x;}
    	inline int min(int x,int y){return x<y?x:y;}
    	int head[N],cnt=1,dep[N],S,T,n,m,maxx,a[N][N];
    	int fx[4]={1,0,-1,0},fy[4]={0,1,0,-1};
    	inline void adde(int u,int v,int w)
    	{
    		e[++cnt].lim=w; e[cnt].nxt=head[u]; e[cnt].to=v;
    		return head[u]=cnt,void();
    	} 
    	queue<int>q; 
    	inline void add(int u,int v,int w){return adde(u,v,w),adde(v,u,0);}
    	inline bool bfs()
    	{
    		memset(dep,0,sizeof(dep)); dep[S]=1; 
    		while(q.size()) q.pop(); q.push(S);
    		while(!q.empty())
    		{
    			int fr=q.front(); q.pop(); 
    			for(int i=head[fr];i;i=e[i].nxt)
    			{
    				int t=e[i].to;
    				if(!dep[t]&&e[i].lim) dep[t]=dep[fr]+1,q.push(t); 
    			}
    		}
    		return dep[T];
    	}
    	inline int dfs(int now,int in)
    	{
    		if(now==T) return in; int out=0;
    		for(int i=head[now];i&&in;i=e[i].nxt)
    		{
    			int t=e[i].to;
    			if(e[i].lim&&dep[t]==dep[now]+1)
    			{
    				int res=dfs(t,min(in,e[i].lim));
    				in-=res; out+=res; e[i].lim-=res;
    				e[i^1].lim+=res;
    			}
    		}if(!out) dep[now]=0;
    		return out;
    	 } 
    	inline int id(int x,int y){return (x-1)*m+y;}
    	inline bool in(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m;}
    	inline bool check(int val)
    	{
    		S=n*m+1; T=n*m+2;
    		int sum=0; 
    		memset(head,0,sizeof(head)); cnt=1;
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=1;j<=m;++j)
    			{
    				if((i+j)%2==0)
    				{
    					add(S,id(i,j),val-a[i][j]); sum+=val-a[i][j];
    					for(int k=0;k<4;++k)
    					{
    						int tx=fx[k]+i,ty=fy[k]+j;
    						if(in(tx,ty)) add(id(i,j),id(tx,ty),1e18+10);
    					}
    				}
    				else add(id(i,j),T,val-a[i][j]);
    			}
    		}
    		int res=0;
    		while(bfs()) res+=dfs(S,1e18+10);
    		return res==sum;
    	}
    	inline void work()
    	{
    		int num[2]={0},sum[2]={0};
    		n=read(); m=read(); maxx=0;
    		for(int i=1;i<=n;++i) 
    		{
    			for(int j=1;j<=m;++j)
    			{
    				a[i][j]=read(); 
    				maxx=max(maxx,a[i][j]);
    				num[(i+j)&1]++; sum[(i+j)&1]+=a[i][j];
    			}
    		}
    		if(num[0]==num[1]) 
    		{
    			if(sum[1]!=sum[0]) return puts("-1"),void();
    			int l=maxx,r=1e18,ans;
    			while(l<=r)
    			{
    				int mid=(l+r)>>1;
    				if(check(mid)) ans=mid,r=mid-1;
    				else l=mid+1;
    			}
    			if(ans==1e18) return puts("-1"),void();
    			else return printf("%lld
    ",ans*num[1]-sum[1]),void();
    		}
    		else
    		{
    			int x=(sum[0]-sum[1])/(num[0]-num[1]);
    			if(x>=maxx&&check(x)) printf("%lld
    ",x*num[1]-sum[1]);
    			else return puts("-1"),void();
    		} return ;
    	}
    	signed main()
    	{
    //		freopen("8.in","r",stdin); 
    		int T=read(); while(T--) work();
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    SpringBoot进阶教程(六十二)整合Kafka
    98每日博客
    96每日博客
    95日每周总结
    829每周总结
    815每周总结
    81每周总结
    822每周总结
    97每日博客
    88每周总结
  • 原文地址:https://www.cnblogs.com/yspm/p/13082556.html
Copyright © 2011-2022 走看看