• fzyzojP3618 -- [校内训练-互测20180412]士兵的游戏


    二分图匈牙利也可以

    判断必须点就看能不能通过偶数长度的增广路翻过去

    代码:

    (最后一个点4s多才行,,,卡不过算了)

     开始边数写少了RE,应该是4*N*N

    M-R随手开了一堆int?都要是long long

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=100+5;
    ll a[N][N];
    int co[N*N];
    int in[N*N];
    int n,m;
    struct node{
        int nxt,to;
    }e[8*N*N];
    int hd[N*N],cnt;
    int num(int x,int y){
        return (x-1)*m+y;
    }
    void add(int x,int y){
    //    cout<<" ahahhaa "<<endl;
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        hd[x]=cnt;
    }
    int to[N*N];
    int vis[N*N];
    bool dfs(int x,int id){
    //    cout<<" x "<<x<<" id "<<id<<endl;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
        //    cout<<" yy "<<y<<" vis "<<vis[y]<<endl;
            if(vis[y]==id) continue;
            vis[y]=id;
            if(!to[y]||dfs(to[y],id)){
                to[y]=x;
                in[x]=1;
                to[x]=y;
                in[y]=1;
                return true;
            }
        }
        return false;
    }
    bool fin(int x,int id,int pos){
        if(vis[x]==id) return false;
        vis[x]=id;
        if(pos==0){
            if(!to[x]) return true;
            return fin(to[x],id,pos^1);
        }
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y!=to[x]){
                if(fin(y,id,pos^1)) return true;
            }
        }
        return false;
    }
    ll p[10]={2,3,7,61,24251};
    ll add(ll x,ll y,ll p){
        return x+y>=p?x+y-p:x+y;
    }
    ll qk(ll x,ll y,ll p){
        ll ret=0;
        while(y){
            if(y&1) ret=add(ret,x,p);
            x=add(x,x,p);
            y>>=1;
        }
        return ret;
    }
    ll qm(ll x,ll y,ll p){
        ll ret=1;
        while(y){
            if(y&1) ret=qk(ret,x,p);
            x=qk(x,x,p);
            y>>=1;
        }
        return ret;
    }
    bool che(ll x,ll d){
        int s=0;
        ll lp=x-1;
        while(!(lp&1)){
            ++s;lp>>=1;
        }
        ll now=qm(d,lp,x);
        if(now==1||now==x-1) return true;
        for(reg i=0;i<s;++i){
            ll tmp=qk(now,now,x);
            if(tmp==1&&(now!=1&&now!=x-1)) return false;
            now=tmp;
        }
        if(now!=1) return false;
        return true;
    }
    bool M_R(ll x){
    //    cout<<" xx "<<x<<endl;
        if(x==0) return true;
        if(x==1) return true;
        if(x==46856248255981ll) return false; 
        if(x==2||x==3||x==7||x==11||x==13||x==17||x==23||x==29||x==31||x==61||x==24251) return true;
        for(reg i=0;i<5;++i){
            if(x%p[i]==0) return false;
            if(!che(x,p[i])) return false;
        }
    //    cout<<" ok "<<endl;
        return true;
    }
    int mem[N*N],nb;
    int main(){
    //    cout<<" M_R "<<M_R(1557403521852231)<<endl;
        rd(n);rd(m);
    //    cout<<" 2333 "<<endl;
        for(reg i=1;i<=n;++i){
            for(reg j=1;j<=m;++j){
                scanf("%lld",&a[i][j]);
                co[num(i,j)]=(i+j)%2;
            }
        }
        
    //    return 0;
        for(reg i=1;i<=n;++i){
            for(reg j=1;j<=m;++j){
                if(a[i][j]==-1) continue;
                if(j!=m){
                    if(a[i][j+1]!=-1){
                        if(M_R(a[i][j]+a[i][j+1])==0){
                            add(num(i,j),num(i,j+1));
                            add(num(i,j+1),num(i,j));
                        }
                    }
                }
                if(i!=n){
                    if(a[i+1][j]!=-1){
                        if(M_R(a[i][j]+a[i+1][j])==0){
                            add(num(i,j),num(i+1,j));
                            add(num(i+1,j),num(i,j));
                    //        cout<<num(i,j)<<" "<<num(i+1,j)<<endl;
                        }
                    }
                }
            }
        }
    //    cout<<" after build "<<endl;
        int tot=0;
        int le=0,ri=0;
        for(reg i=1;i<=n;++i){
            for(reg j=1;j<=m;++j){
                if(co[num(i,j)]==0&&a[i][j]!=-1){
                    ++le;
                    tot+=dfs(num(i,j),num(i,j));
                }else if(a[i][j]!=-1) ++ri;
            }
        }
    //    cout<<" le ri "<<le<<" "<<ri<<" tot "<<tot<<endl;
        if(le==ri&&tot==le){
            puts("0");return 0;
        }
        memset(vis,0,sizeof vis);
        for(reg i=1;i<=n;++i){
            for(reg j=1;j<=m;++j){
                if(a[i][j]!=-1){
                    if(!in[num(i,j)]||fin(to[num(i,j)],num(i,j),1)){
                        mem[++nb]=num(i,j);
                    }
                }
            }
        }
        sort(mem+1,mem+nb+1);
        printf("%d
    ",nb);
        for(reg i=1;i<=nb;++i){
            printf("%d %d
    ",(mem[i]-1)/m+1,mem[i]-((mem[i]-1)/m)*m);
        }
        return 0;
    }
    
    }
    signed main(){
    //    freopen("data3618.in","r",stdin);
    //    freopen("data3618.out","w",stdout);
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/2 20:45:23
    */

    这个题的二分图匹配思想还是很巧妙

    从最大匹配来考虑,便于决策

  • 相关阅读:
    做了个专门针对少儿编程教程的网站,有兴趣的可以来逛逛
    解决 supervisor : 无法加载文件 C:UserscharlesAppDataRoaming pmsupervisor.ps1
    node.js03 第一个node.js程序和读取文件
    .net图表之ECharts随笔06-这才是最简单的
    .net图表之ECharts随笔05-不同01的语法步骤
    .net图表之ECharts随笔04-散点图
    .net图表之ECharts随笔03-热力地图
    .net图表之ECharts随笔02-字符云
    .net图表之ECharts随笔01-最简单的使用步骤
    Python学习之全局变量与global
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10349457.html
Copyright © 2020-2023  润新知