[LibreOJ Round #11]Misaka Network 与测试

壹、题目

传送门 to LOJ

贰、思考

要求有几个:

  1. 矩阵不交;
  2. 平均值为 \(2\)
  3. 不能有 *

如果没有要求 \(2\),要求最多的矩阵,不就输出......

有要求 \(2\),首先较为贪心地考虑,有 \(2\) 就自成一个矩阵?这样会出问题吗?比如为了让 \(2\) 自成一个矩阵,破坏了更多矩阵?但是我们破坏了一个矩阵,也让一个 \(2\) 自成了矩阵,就这样考虑似乎是不会出问题的。

然后,对于一个 \(3\),它必定会和一个 \(1\) 配对,对于 \(1\) 也是如此,贪心地,一个 \(1\) 和一个 \(3\) 配对是最优的,并且为了使测试尽可能多,矩阵尽量小,所以 "相邻" 的 \(1,3\) 配一起?所以这只是一个简简单单的二分图匹配?\(\text{have a try}\)......然后......就过了......

细细想一下,好像确实是这个样子的,因为无论什么情况,只要一个矩阵中划分出多于一组的 \(\lang 1,3\rang\),就可以拆成至少也是等价个数,甚至有可能会更多的矩阵数量。

所以这个贪心应该是对的 因为我想不出反例

叁、代码

using namespace Elaina;

const int maxn=1e5;

int n,m,ans;
int** a;

char c[maxn+5];

inline void input(){
    n=readin(1),m=readin(1);
    a=new int*[n+5];
    rep(i,1,n)a[i]=new int[m+5];
    rep(i,1,n){
        scanf("%s",c+1);
        rep(j,1,m){
            if(c[j]=='*')a[i][j]=-1;
            else a[i][j]=c[j]-'0';
            ans+=(a[i][j]==2);
        }
    }
}


int dir[][2]={{0,1},{0,-1},{-1,0},{1,0}};
inline int getid(const int i,const int j){
    return (i-1)*m+j;
}
struct edge{int to,nxt;
    edge(const int T=0,const int N=0):to(T),nxt(N){}
}e[maxn+5];
int tail[maxn+5],ecnt;
inline void add_edge(const int u,const int v){
    e[++ecnt]=edge(v,tail[u]);tail[u]=ecnt;
}
inline int inside(const int x,const int y){
    return 0<x && x<=n && 0<y && y<=m;
}
inline void build(){
    rep(i,1,n)rep(j,1,m)if(a[i][j]==1){
        for(int k=0;k<4;++k){
            int tx=i+dir[k][0];
            int ty=j+dir[k][1];
            if(!inside(tx,ty))continue;
            if(a[tx][ty]==3)add_edge(getid(i,j),getid(tx,ty));
        }
    }
}

int vis[maxn+5],match[maxn+5];
int dfs(const int u){
    for(int i=tail[u],v;i;i=e[i].nxt)if(!vis[v=e[i].to]){
        vis[v]=1;
        if(!match[v] || dfs(match[v])){
            match[v]=u;
            return 1;
        }
    }
    return 0;
}
inline void hungary(){
    for(int i=1;i<=n*m;++i){
        memset(vis+1,0,(n*m)<<2);
        if(dfs(i))++ans;
    }
    writc(ans,'\n');
}

signed main(){
    input();
    build();
    hungary();
    return 0;
}

肆、用到の小 \(\tt trick\)

可以先从题目的一些性质、特征贪心地入手,这样可能对思路有所启发.

posted @ 2021-02-05 18:03  Arextre  阅读(126)  评论(0编辑  收藏  举报