zoukankan      html  css  js  c++  java
  • spoj2142 Arranging Flowers

    传送门

    题目大意

    给你n和m,表示一个n*n的数独已经填完了m行,让你填出剩下几行,要求答案的字典序最小。

    分析

    看到这道题我首先想到的是记录每行每列使用了哪些数字,然后贪心的来填,但是发现用这种策略会在有些情况下得不到解。于是我们考虑二分图匹配,将左边n个点表示每一行n个位置,右边n个点表示对应的n个数,我们一行一行的填,每填一行,便将产生的对应关系所代表的边删掉。那我们考虑如何二分图匹配可以得到字典序最小的答案,我们先进行一边常规的二分图匹配,然后枚举1到n每一个位置,找所有现在比位置j对应的值小且位置在j之后的k替换现在j对应的值,检测是否可以替换。注意这里的used数组只需每个j清空一次,因为j是一个固定的值,所以之前不行的值,随着k的改变仍然不行。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    #define li long long
    #define pb push_back
    #define mp make_pair
    #define y1 y12345678909
    #define rii register int
    #define pii pair<int,int>
    #define r(x) scanf("%d",&x)
    #define ck(x) cout<<x<<endl;
    #define uli unsigned long long
    #define clr(x) memset(x,0,sizeof(x))
    #define sp cout<<"------------------------------------------------------"<<endl
    int g[222],nxt[222][222],pre[222][222],belong[222],T,used[222],n,m,back[222];
    inline void del(int x,int y){
          if(g[x]==y)g[x]=nxt[x][y];
            else {
              nxt[x][pre[x][y]]=nxt[x][y];
              pre[x][nxt[x][y]]=pre[x][y];
            }
          return;
    }
    inline bool work(int x,int lit){
          for(rii i=g[x];i;i=nxt[x][i])
            if(used[i]!=T){
              used[i]=T;
              if(!belong[i]||(belong[i]>lit&&work(belong[i],lit))){
                  belong[i]=x;
                  back[x]=i;
                  return 1;
              }
            }
          return 0;
    }
    inline void go(){
          for(rii i=1;i<=n;++i){
              T++;
              work(i,0);
          }
          for(rii j=1;j<=n;++j){
              T++;
            for(rii k=g[j];k;k=nxt[j][k]){
                if(belong[k]==j)break;
                if(belong[k]<j)continue;
                int x=belong[k],y=back[j];
                belong[back[j]]=0;
                back[belong[k]]=0;
                belong[k]=j;
                back[j]=k;
                if(work(x,j))break;
                back[x]=k;
                belong[k]=x;
                belong[y]=j;
                back[j]=y;
            }
          }
          return;
    }
    int main(){
          int i,j,k,t,x;
          r(t);
          while(t--){
            r(n),r(m);
            clr(pre),clr(nxt);
            for(rii i=1;i<=n;++i){
              g[i]=1;
              int now=1;
              for(rii j=2;j<=n;++j){
                  nxt[i][now]=j;
                  pre[i][j]=now;
                  now=j;
              }
            }
            for(rii i=1;i<=m;++i)
              for(rii j=1;j<=n;++j){
                  r(x);
                  del(j,x);
              }
            ck(n-m);
            for(rii i=m+1;i<=n;++i){
              T=0;
              clr(back);
              clr(belong);
              clr(used);
              go();
              for(rii j=1;j<=n;++j)
                del(j,back[j]);
              for(rii j=1;j<=n;++j)printf("%d ",back[j]);
              puts("");
            }
          }
          return 0;
    }
  • 相关阅读:
    关于C++类中的静态数据成员
    关于C++中char,sizeof,strlen,string
    C++学习笔记(7)
    C++学习笔记(6)
    C++学习笔记(指针)
    C++学习笔记(4)
    UVA 10780
    UVA 531
    HDU, 3579 Hello Kiki
    UVA, 10413 Crazy Savages
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9428348.html
Copyright © 2011-2022 走看看