[TJOI2011]构造矩阵

Posted dyx_diversion

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TJOI2011]构造矩阵相关的知识,希望对你有一定的参考价值。

  • 考虑优化贪心,不回溯,对于每一位,你都判一下放0的话后面是否有解,用网络流判是否可以完美匹配就行了。
  • 但这样时间复杂是错的,所以不必每次都重新建图,现在原来的图中看一下该行列是否已经匹配,若没有,则强制该行列匹配,重新建图,看是否完美匹配即可
  • 时间复杂度好像是错的?首先,随着你点放的点越来越多,你的图会越来越小,跑的越来越快。其次,有很多行列在原来的途中就已经匹配,不必每次都跑。最后,它可以飞快的通过本题。
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=100+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
  T ans=0,f=1;
  char ch=getchar();
  while(!isdigit(ch)&&ch!=‘-‘)ch=getchar();
  if(ch==‘-‘)f=-1,ch=getchar();
  while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-‘0‘),ch=getchar();
  return ans*f;
}
template<typename T>void write(T x,char y)
{
  if(x==0)
  {
      putchar(‘0‘);
      return;
  }
  if(x<0)
  {
      putchar(‘-‘);
      x=-x;
  }
  static char wr[20];
  int top=0;
  for(;x;x/=10)wr[++top]=x%10+‘0‘;
  while(top)putchar(wr[top--]);
  putchar(y);
}
void file()
{
  #ifndef ONLINE_JUDGE
      freopen("1418.in","r",stdin);
      freopen("1418.out","w",stdout);
  #endif
}
int n,m;
int r[N],c[N];
int mp[N][N];
void input()
{
    n=read<int>(),m=read<int>();
    For(i,1,n)r[i]=m-read<int>();
    For(j,1,m)c[j]=n-read<int>();
}
const int M=1e5+5;
struct edge
{
    int v,flow,nex;
}e[M];
int head[N<<1],tt=1;
void add(int x,int y,int flow)
{
    e[++tt]=(edge){y,flow,head[x]},head[x]=tt;
    e[++tt]=(edge){x,0,head[y]},head[y]=tt;
}
int s,t,dis[N<<1],gap[N<<1],cur[N<<1];
const int inf=0x3f3f3f3f;
int dfs(int u,int flow)
{
    if(u==t)return flow;
    int res=flow,v,f;
    for(register int &i=cur[u];i;i=e[i].nex)
    {
        v=e[i].v;
        if(dis[u]==dis[v]+1&&e[i].flow)
        {
            f=dfs(v,min(res,e[i].flow));
            e[i].flow-=f,e[i^1].flow+=f;
            if(!(res-=f))return flow;
        }
    }
    if(!--gap[dis[u]])dis[s]=t;
    ++gap[++dis[u]];
    return flow-res;
}
int isap()
{
    memset(gap,0,sizeof gap);
    memset(dis,0,sizeof dis);
    int res=0;
    for(gap[0]=t;dis[s]<t;)
    {
        memcpy(cur,head,sizeof cur);
        res+=dfs(s,inf);
    }
    return res;
}
int judge;
void rebuild(int x,int y)
{
    memset(head,0,sizeof head);
    tt=1,judge=0;
    s=n+m+1,t=s+1;
    For(i,1,n)add(s,i,r[i]),judge+=r[i];
    For(j,1,m)add(j+n,t,c[j]);
    For(j,y+1,m)add(x,j+n,1);
    For(i,x+1,n)For(j,1,m)add(i,j+n,1);
}
int check(int x,int y)
{
    --r[x],--c[y];
    int v;
    for(register int i=head[x];i;i=e[i].nex)
    {
        v=e[i].v;
        if(v==y+n&&!e[i].flow)return 1;
    }
    rebuild(x,y);
    if(judge==isap())return 1;
    ++r[x],++c[y];
    if(y==1)rebuild(x-1,m);
    else rebuild(x,y-1);
    isap();
    return 0;
}
void out()
{
    For(i,1,n)
    {
        For(j,1,m)printf("%d",mp[i][j]);
        puts("");
    }
}
void work()
{
    For(x,1,n)For(y,1,m)
    {   
        if(r[x]&&c[y]&&check(x,y))
        {
            mp[x][y]=0;
        }
        else 
        {
            mp[x][y]=1;
        }
    }
}
int main()
{
    file();
    input();
    rebuild(1,0);
    isap();
    work();
    out();
    return 0;
}

以上是关于[TJOI2011]构造矩阵的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4887:[Tjoi2017]可乐 矩阵乘法,快速幂

BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

bzoj3996:[TJOI2015]线性代数

bzoj3996 [TJOI2015]线性代数

BZOJ3996[TJOI2015]线性代数

BZOJ3996: [TJOI2015]线性代数