• 【LOJ2321 「清华集训」2017无限之环】 题解


    在经过 \(n\) 个小时的奋斗后,LsWn 终于 AC 了这个毒瘤题。

    题面传送门

    如果你更喜欢洛谷的话戳这里

    我们先看一个正确可以流通的图 (加上了黑白相间染色,然后黄色方块代表这个格子的上方,红色代表下方,紫色是左,灰色是右)(最后一行的上下画反了……凑活凑活)。

    黑白染色网络流一贯的套路,将黑点流向白点,源点流向黑点,白点流向汇点,然后根据拆点一贯的套路,内部连边。(指一个点拆成五个点,中间和上下左右)

    显然,合理的方案就是所有的黑点和白点互相匹配,即有完备匹配,也就是满流,没有一滴水漏出来。从黑点流出的点都有去处。

    这是一个合法方案。那么如果出了点小差错,需要旋转呢?

    这就很谔谔,右下角没法连通。但是我们可以旋转。我们观察到,左旋一次,相当于把右插头换成左插头。于是连费用为 \(1\) 的边。

    右旋一次,相当于把下插头换成上插头,于是连边。。旋转两次,走两次旋转一次,故不连边。

    现在讨论连边情况:

    1. 类似于 ┌
      上面已经讲过,不再陈述。
    2. 类似于 Q
      如果左/右翻转,那么就等于插头向左/右换。翻转两次就是上下换,左右换。换两次的连边的费用是 \(2\)
    3. 类似于丨
      不处理,因为不能转。
    4. 类似于 T
      和 ┌ 比较相似。不过需要连上下边。
      5 类似于 十
      不处理,因为转了也没用。

    然后总体 \(15\) 种情况还需一一分析……这就很毒瘤。这就放在代码中了。

    一些细节:

    1. 不要重复建边!不要重复建边!不要重复建边!(否则你算出来的答案会小于标准答案)
    2. 毒瘤建边题的网络流真的不能码错!真的不能!
    3. hsh 函数一定要注意!
    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=5e6+9,inf=0x3f3f3f3f3f3f3f3f;
    int n,m,a[2009][2009],debugger;
    
    struct edge{int to,nxt,c,w;}e[N*2]; int hd[N],tot=1;
    void add(int u,int v,int c,int w){e[++tot]=(edge){v,hd[u],c,w};hd[u]=tot;}
    void addh(int u,int v,int c,int w){
    	//cout<<u<<" "<<v<<" "<<c<<" "<<w<<endl;
    	debugger+=w;
    	add(u,v,c,w),add(v,u,0,-w);
    }
    void addr(int u,int v,int c,int w){addh(v,u,c,w);}
    
    int s,t,flow,cost,tmp,ans;
    int d[N]; bool in[N]; 
    bool spfa(){
    	queue<int>q; q.push(s); memset(d,0x3f,sizeof(d)); d[s]=0;
    	while(!q.empty()){
    		int u=q.front(); q.pop(); in[u]=0;
    		for(int i=hd[u],v;i;i=e[i].nxt)
    			if(e[i].c&&d[v=e[i].to]>d[u]+e[i].w){
    				d[v]=d[u]+e[i].w;
    				if(!in[v]) q.push(v),in[v]=1;
    			}
    	}
    	return d[t]<inf;
    }
    int dinic(int u,int flow){
    	int rest=flow; if(u==t) return flow; in[u]=1;
    	for(int i=hd[u],v;i&&rest;i=e[i].nxt)
    		if(!in[v=e[i].to]&&e[i].c&&d[v]==d[u]+e[i].w){
    			int used=dinic(v,min(e[i].c,rest));
    			if(!used) d[v]=-1;
    			rest-=used; e[i].c-=used,e[i^1].c+=used,cost+=used*e[i].w; 
    		}
    	in[u]=0;
    	return flow-rest;
    }
    
    // 0:中  1:上  2:右  3:下  4:左 
    int hsh(int x,int y,int loc){return (x*m-m+y)+loc*m*n;}
    bool ok(int x,int y){return x>0&&x<=n&&y>0&&y<=m;}
    signed main(){
    	scanf("%lld%lld",&n,&m); s=n*m*5+1,t=n*m*5+2;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			scanf("%lld",&a[i][j]);
    
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
    		if((i+j)%2){ //黑格子 
    			addh(s,hsh(i,j,0),inf,0);
    			if(ok(i-1,j))
    				addh(hsh(i,j,1),hsh(i-1,j,3),1,0);
    			if(ok(i,j+1))
    				addh(hsh(i,j,2),hsh(i,j+1,4),1,0);
    			if(ok(i+1,j))	
    				addh(hsh(i,j,3),hsh(i+1,j,1),1,0);
    			if(ok(i,j-1))
    				addh(hsh(i,j,4),hsh(i,j-1,2),1,0);
    			for(int k=1;k<=4;k++)
    				if(a[i][j]&(1ll<<(k-1))){
    					addh(hsh(i,j,0),hsh(i,j,k),1,0);
    					ans++;
    				}
    			if(a[i][j]==15);	 //全 
    			else if(a[i][j]==1){ //上 
    				addh(hsh(i,j,1),hsh(i,j,2),1,1);
    				addh(hsh(i,j,1),hsh(i,j,4),1,1);
    				addh(hsh(i,j,1),hsh(i,j,3),1,2);
    			}
    			else if(a[i][j]==2){ //右
    				addh(hsh(i,j,2),hsh(i,j,1),1,1);
    				addh(hsh(i,j,2),hsh(i,j,3),1,1);
    				addh(hsh(i,j,2),hsh(i,j,4),1,2);
    			} 
    			else if(a[i][j]==3){ //上右 
    				addh(hsh(i,j,1),hsh(i,j,3),1,1);
    				addh(hsh(i,j,2),hsh(i,j,4),1,1);
    			}
    			else if(a[i][j]==4){ //下 
    				addh(hsh(i,j,3),hsh(i,j,2),1,1);
    				addh(hsh(i,j,3),hsh(i,j,4),1,1);
    				addh(hsh(i,j,3),hsh(i,j,1),1,2);
    			} 
    			else if(a[i][j]==5); //上下 
    			else if(a[i][j]==6){ //右下 
    				addh(hsh(i,j,3),hsh(i,j,1),1,1);
    				addh(hsh(i,j,2),hsh(i,j,4),1,1);
    			}
    			else if(a[i][j]==7){ //上右下 
    				addh(hsh(i,j,1),hsh(i,j,4),1,1);
    				addh(hsh(i,j,3),hsh(i,j,4),1,1);
    				addh(hsh(i,j,2),hsh(i,j,4),1,2);
    			}
    			else if(a[i][j]==8){ //左 
    				addh(hsh(i,j,4),hsh(i,j,1),1,1);
    				addh(hsh(i,j,4),hsh(i,j,3),1,1);
    				addh(hsh(i,j,4),hsh(i,j,2),1,2);
    			}
    			else if(a[i][j]==9){ //上左 
    				addh(hsh(i,j,1),hsh(i,j,3),1,1);
    				addh(hsh(i,j,4),hsh(i,j,2),1,1); 
    			}
    			else if(a[i][j]==10);//右左 
    			else if(a[i][j]==11){//上右左 
    				addh(hsh(i,j,2),hsh(i,j,3),1,1);
    				addh(hsh(i,j,4),hsh(i,j,3),1,1);
    				addh(hsh(i,j,1),hsh(i,j,3),1,2);
    			}
    			else if(a[i][j]==12){//下左 
    				addh(hsh(i,j,3),hsh(i,j,1),1,1);
    				addh(hsh(i,j,4),hsh(i,j,2),1,1); 
    			}
    			else if(a[i][j]==13){//上下左 
    				addh(hsh(i,j,1),hsh(i,j,2),1,1);
    				addh(hsh(i,j,3),hsh(i,j,2),1,1);
    				addh(hsh(i,j,4),hsh(i,j,2),1,2);
    			}
    			else if(a[i][j]==14){//右下左 
    				addh(hsh(i,j,2),hsh(i,j,1),1,1);
    				addh(hsh(i,j,4),hsh(i,j,1),1,1);
    				addh(hsh(i,j,3),hsh(i,j,1),1,2);
    			}
    		}
    		else{
    			addh(hsh(i,j,0),t,inf,0);
    			for(int k=1;k<=4;k++)
    				if(a[i][j]&(1<<(k-1))){
    					addr(hsh(i,j,0),hsh(i,j,k),1,0);
    					ans++;
    				}
    			if(a[i][j]==15);	 //全 
    			else if(a[i][j]==1){ //上 
    				addr(hsh(i,j,1),hsh(i,j,2),1,1);
    				addr(hsh(i,j,1),hsh(i,j,4),1,1);
    				addr(hsh(i,j,1),hsh(i,j,3),1,2);
    			}
    			else if(a[i][j]==2){ //右
    				addr(hsh(i,j,2),hsh(i,j,1),1,1);
    				addr(hsh(i,j,2),hsh(i,j,3),1,1);
    				addr(hsh(i,j,2),hsh(i,j,4),1,2);
    			} 
    			else if(a[i][j]==3){ //上右 
    				addr(hsh(i,j,1),hsh(i,j,3),1,1);
    				addr(hsh(i,j,2),hsh(i,j,4),1,1);
    			}
    			else if(a[i][j]==4){ //下 
    				addr(hsh(i,j,3),hsh(i,j,2),1,1);
    				addr(hsh(i,j,3),hsh(i,j,4),1,1);
    				addr(hsh(i,j,3),hsh(i,j,1),1,2);
    			} 
    			else if(a[i][j]==5); //上下 
    			else if(a[i][j]==6){ //右下 
    				addr(hsh(i,j,3),hsh(i,j,1),1,1);
    				addr(hsh(i,j,2),hsh(i,j,4),1,1);
    			}
    			else if(a[i][j]==7){ //上右下 
    				addr(hsh(i,j,1),hsh(i,j,4),1,1);
    				addr(hsh(i,j,3),hsh(i,j,4),1,1);
    				addr(hsh(i,j,2),hsh(i,j,4),1,2);
    			}
    			else if(a[i][j]==8){ //左 
    				addr(hsh(i,j,4),hsh(i,j,1),1,1);
    				addr(hsh(i,j,4),hsh(i,j,3),1,1);
    				addr(hsh(i,j,4),hsh(i,j,2),1,2);
    			}
    			else if(a[i][j]==9){ //上左 
    				addr(hsh(i,j,1),hsh(i,j,3),1,1);
    				addr(hsh(i,j,4),hsh(i,j,2),1,1); 
    			}
    			else if(a[i][j]==10);//右左 
    			else if(a[i][j]==11){//上右左 
    				addr(hsh(i,j,2),hsh(i,j,3),1,1);
    				addr(hsh(i,j,4),hsh(i,j,3),1,1);
    				addr(hsh(i,j,1),hsh(i,j,3),1,2);
    			}
    			else if(a[i][j]==12){//下左 
    				addr(hsh(i,j,3),hsh(i,j,1),1,1);
    				addr(hsh(i,j,4),hsh(i,j,2),1,1); 
    			}
    			else if(a[i][j]==13){//上下左 
    				addr(hsh(i,j,1),hsh(i,j,2),1,1);
    				addr(hsh(i,j,3),hsh(i,j,2),1,1);
    				addr(hsh(i,j,4),hsh(i,j,2),1,2);
    			}
    			else if(a[i][j]==14){//右下左 
    				addr(hsh(i,j,2),hsh(i,j,1),1,1);
    				addr(hsh(i,j,4),hsh(i,j,1),1,1);
    				addr(hsh(i,j,3),hsh(i,j,1),1,2);
    			}
    		}
    	}
    	
    	while(spfa()) while(tmp=dinic(s,inf)) flow+=tmp;
    	if(flow*2==ans) printf("%lld\n",cost);
    	else puts("-1");
    	return 0;
    }
    
  • 相关阅读:
    租房
    NetBeans 时事通讯(刊号 # 103 May 18, 2010)
    美国的车库文化
    新《三国》的两点观后感
    欧洲足球逐渐失去冷门的魅力
    NetBeans 时事通讯(刊号 # 102 May 14, 2010)
    NetBeans 时事通讯(刊号 # 103 May 18, 2010)
    HTML 简史
    租房
    HTML 简史
  • 原文地址:https://www.cnblogs.com/TetrisCandy/p/12781535.html
Copyright © 2020-2023  润新知