图论+倍增——cf

两种思路

找环模拟: 

/*
每个格子都有看成是带一条出边的点(正反图各建一个)
那么形成的图像很多不相交的环,环上带着链
所以可以把环单独拉出来算,每个独立的环+链最多放的数量就是环的size
然后再考虑黑色格子最多
    对于每个独立的环+链,给每个结点编号,定一个环上点为0,其后继是1,前驱是size-1
    用这种方式把整个环+链染好色,然后[0,size-1]没种颜色的点只能有一个 
*/

倍增:https://www.cnblogs.com/suxxsfe/p/12699630.html

#include<bits/stdc++.h>
using namespace std;
#define N 2000006

int n,m,nxt[N][21],cnt[N],f[N];
char mp[N],d[N],tmp[N]; 

int id(int i,int j){
    return (i-1)*m+j; 
}
void init(){
    for(int i=1;i<=n*m;i++)f[i]=cnt[i]=0;
}

int main(){
    int t;cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%s",tmp+1);
            for(int j=1;j<=m;j++)
                mp[id(i,j)]=tmp[j];
        }
        for(int i=1;i<=n;i++){
            scanf("%s",tmp+1);
            for(int j=1;j<=m;j++)
                d[id(i,j)]=tmp[j];
        }
        init();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){                
                int u,v;
                if(d[id(i,j)]=='L'){
                    u=id(i,j),v=id(i,j-1);
                }else if(d[id(i,j)]=='R'){
                    u=id(i,j),v=id(i,j+1);                
                }else if(d[id(i,j)]=='U'){
                    u=id(i,j),v=id(i-1,j);
                }else if(d[id(i,j)]=='D'){
                    u=id(i,j),v=id(i+1,j);
                }
                nxt[u][0]=v;
            }
        int k=0;
        while((1<<(k+1))<n*m)
            k++;
        for(int i=1;i<=k;i++){
            for(int j=1;j<=n*m;j++)
                nxt[j][i]=nxt[nxt[j][i-1]][i-1];
        }
        
        //for(int i=1;i<=n*m;i++)cout<<nxt[i][0]<<" ";
        
        for(int i=1;i<=n*m;i++){
            int now=n*m,u=i;
            for(int j=k;j>=0;j--)if(now>=(1<<j)){
                now-=(1<<j);
                u=nxt[u][j];
            }
            f[u]++;
            if(mp[i]=='0')cnt[u]++;
        }
        
        int sum1=0,sum2=0;
        for(int i=1;i<=n*m;i++){
            if(f[i])sum1++;
            if(cnt[i])sum2++;
        }
        cout<<sum1<<" "<<sum2<<'
';
    }
} 
原文地址:https://www.cnblogs.com/zsben991126/p/12770739.html