2020 ICPC, COMPFEST 12, Indonesia Multi-Provincial Contest

  前两个个小时过了五题,后三个小时一题没过,三个人盯一份代码盯了2个小时愣是没看出来,心态爆炸。

  题意是给你一朵花状无向图,两个人同时走,A走过的边染成蓝色,B走过的边染成红色,走过的边就不能再走,直到其中一个人不能走的时候停下来,问有多少种染色方案。

  很显然,我们可以把这朵花拍成数列,那么就是三种情况。

  1、两个人在某一朵花瓣上相遇然后停止。

  2、两个人各走个的环,走完整张图。

  3、两个人各走各的,最后剩一条边。

  那么我们就维护前后缀dp值,枚举那个环相遇然后合并就好了。

  于是呢,我们把23当成一种情况考虑了,根本没有考虑少走一条边的人会在那个环停下来,GG。

#include<bits/stdc++.h>
using namespace std;
#define rll register ll
#define IL inline
#define rep(i,h,t) for (rll i=h;i<=t;i++)
#define dep(i,t,h) for (rll i=t;i>=h;i--)
#define mid ((h+t)>>1)
#define ll long long
const ll mo=1e9+7;
const ll N=10000;
struct re{
    ll a,b,c;
}e[N*2];
ll head[N],l,c[N],cnt,n,m;
ll f1[3000][5000],f2[3000][5000];
IL void arr(ll x,ll y)
{
    e[++l].a=head[x];
    e[l].b=y;
    head[x]=l;
}
void cl(ll x)
{
    if (x%2==1) e[x].c=1,e[x+1].c=1;
    else e[x].c=1,e[x-1].c=1;
}
void dfs(ll x,ll y)
{
    if (x==1)
    {
        c[++cnt]=y; return;
    }
    for(rll u=head[x];u;u=e[u].a)
    {
        ll v=e[u].b;
        if (!e[u].c)
        {
            cl(u);
            dfs(v,y+1);
        }
    }
}
int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  rep(i,1,m)
  {
      ll x,y;
      cin>>x>>y;
      arr(x,y); arr(y,x);
  }
  for (rll u=head[1];u;u=e[u].a)
  {
      ll v=e[u].b;
      if (e[u].c==0)
      {
          cl(u);
          dfs(v,1);
      }
  }
  ll sum=0;
  for(int i=1;i<=cnt;++i)sum+=c[i];
  m=cnt;
  f1[0][2000]=1;
  rep(i,1,m)
  {
      dep(j,4000,c[i])
        f1[i][j]=(f1[i-1][j]+f1[i-1][j-c[i]])%mo;
    rep(j,0,4000-c[i])
      f1[i][j]=(f1[i][j]+f1[i-1][j+c[i]])%mo; 
  }
  f2[m+1][2000]=1;
  dep(i,m,1)
  {
      dep(j,4000,c[i])
        f2[i][j]=(f2[i+1][j]+f2[i+1][j-c[i]])%mo;
    rep(j,0,4000-c[i])
      f2[i][j]=(f2[i][j]+f2[i+1][j+c[i]])%mo; 
  }
  ll ans=0;
  rep(i,1,m)
  {
      rep(i1,0,4000)
        if (f1[i-1][i1]>0)
        rep(j1,max(0ll,4000-c[i]-i1),min(4000ll,4000+c[i]-i1))
          if (f2[i+1][j1]>0)
          {
              ll now=1ll*f1[i-1][i1]*f2[i+1][j1]%mo;
              ll kk=abs(i1+j1-4000);
              if (c[i]-2>=kk) ans=(ans+now)%mo;
          }
  }
  ans=ans*2%mo;
 // for(int i=1;i<=cnt;++i)cout<<c[i]<<" ";
  if(sum%2==1){
          memset(f1,0,sizeof(f1));
      memset(f2,0,sizeof(f2)); 
        f1[0][2000]=1;
  rep(i,1,m)
  {
      dep(j,4000,c[i])
        f1[i][j]=(f1[i][j]+f1[i-1][j-c[i]])%mo;
    rep(j,0,4000-c[i])
      f1[i][j]=(f1[i][j]+f1[i-1][j+c[i]])%mo; 
  }
  f2[m+1][2000]=1;
  dep(i,m,1)
  {
      dep(j,4000,c[i])
        f2[i][j]=(f2[i][j]+f2[i+1][j-c[i]])%mo;
    rep(j,0,4000-c[i])
      f2[i][j]=(f2[i][j]+f2[i+1][j+c[i]])%mo; 
  }
  for(int i=1;i<=m;++i){
      for(int j=0;j<=4000;++j){
      if(4000+c[i]-1-j>=0&&4000+c[i]-1-j<=4000)
        (ans+=f1[i-1][j]*f2[i+1][4000+c[i]-1-j]%mo*2)%=mo;
        if(4000-c[i]+1-j>=0&&4000-c[i]+1-j<=4000)
        (ans+=f1[i-1][j]*f2[i+1][4000-c[i]+1-j]%mo*2)%=mo;
   }
  }
  }
  else{
    memset(f1,0,sizeof(f1));
    f1[0][2000]=1;
    rep(i,1,m)
     {
        dep(j,4000,c[i])
          f1[i][j]=f1[i-1][j-c[i]]%mo;
      rep(j,0,4000-c[i])
        f1[i][j]=(f1[i][j]+f1[i-1][j+c[i]])%mo; 
     } 
     ans=(1ll*ans+f1[m][2000]+1ll*(f1[m][2001]+f1[m][1999])*2)%mo;
  }

  cout<<ans<<endl;
  return 0; 
}

    

    

原文地址:https://www.cnblogs.com/ZH-comld/p/13741677.html