[WC2016]問題解決の挑戦NPCレポート

[WC2016]挑戦NPC

問題の意味

そこ\(N- \)ボール、\(M \)バスケット、\(E \)条件\((U、V)\) ショー球状\(U \)バスケットに入れることができます\(V \)内部。

各ボールがバスケットに配置する必要があり、各バスケットはまで置くことができます\(3 \)数は超えていない場合はボール、バスケットボール(1 \)\、バスケットがあったと主張し、フル半分の。

多くのバスケットは半分、およびプログラムの出力に作ることができるか尋ねてください。

バスケットに各ボールするようにデータを確実にするソリューションが存在しなければなりません。

思考

マッチングの問題。

入れバスケットだけで3個のボールを入れて見バスケットを

バスケット場合は半分がいっぱい、それは、少なくともでなければなりません\(2 \)バスケットを空にします。

2つの空のバスケットのために、彼らは彼らが今一致させ、その後、他のボールを一致させることができません。

したがって、点のようなボールの各々は、各バスケットのための3つの点として、シーク最大整合グラフは、一般的に良い、花とボードのセット。(花の研究ノートと

各ボールがバスケットに入れなければならないので、それほど増大経路を見つけるための出発点として、第1のボール:音符。

コード

#include<bits/stdc++.h>
using namespace std;
const int __=600+7;
const int ___=200000+7;    // 记得算好总共有多少条边
int T,n,m,e,col[__],pre[__],mat[__],fa[__],fp[__],sym,ans,bel[__],tota;
int lst[__],nxt[___],to[___],tot;
queue<int> q;
void add(int x,int y){ nxt[++tot]=lst[x]; to[tot]=y; lst[x]=tot; }
int find(int x){ return fa[x]==x ?x :fa[x]=find(fa[x]); }
int Lca(int x,int y){
  sym++;
  while(1){
    if(x){
      x=find(x);
      if(fp[x]==sym) return x;
      else{ fp[x]=sym; x=pre[mat[x]]; }
    }
    swap(x,y);
  }
  return 0;
}
void con(int x,int y,int lca){
  while(find(x)!=lca){
    pre[x]=y; fa[x]=lca;
    y=mat[x];
    col[y]=1; q.push(y);
    mat[y]=x; fa[y]=lca;
    x=pre[y];
  }
}
bool aug(int x){
  for(int i=1;i<=tota;i++){ col[i]=pre[i]=0; fa[i]=i; }
  while(!q.empty()) q.pop();
  q.push(x); col[x]=1;
  while(!q.empty()){
    int u=q.front(); q.pop();
    for(int i=lst[u];i;i=nxt[i]){
      int v=to[i];
      if(find(u)==find(v)||col[v]==2) continue;
      if(!col[v]){
    pre[v]=u; col[v]=2;
    if(!mat[v]){
      while(v){
        int t=mat[pre[v]];
        mat[v]=pre[v];
        mat[pre[v]]=v;
        v=t;
      }
      return 1;
    }
    else{ col[mat[v]]=1; q.push(mat[v]); }
      }
      else{
    int lca=Lca(u,v);
    con(u,v,lca); con(v,u,lca);
      }
    }
  }
  return 0;
}
int main(){
  //freopen("x.in","r",stdin);
  cin>>T;
  while(T--){
    scanf("%d%d%d",&n,&m,&e);
    int x,y; tot=ans=0; tota=n+3*m;
    memset(lst,0,sizeof(lst));
    memset(mat,0,sizeof(mat));
    for(int i=1;i<=e;i++){
      scanf("%d%d",&x,&y);
      add(x,y+n); add(y+n,x);
      add(x,y+n+m); add(y+n+m,x);
      add(x,y+n+m+m); add(y+n+m+m,x);
    }
    for(int i=1;i<=m;i++){
      add(i+n,i+n+m); add(i+n+m,i+n);
      add(i+n,i+n+m+m); add(i+n+m+m,i+n);
      add(i+n+m,i+n+m+m); add(i+n+m+m,i+n+m);
      bel[i+n]=bel[i+n+m]=bel[i+n+m+m]=i;
    }
    for(int i=1;i<=tota;i++){
      if(!mat[i]) ans+=aug(i);
    }
    printf("%d\n",ans-n);
    for(int i=1;i<=n;i++) printf("%d ",bel[mat[i]]); putchar('\n');
  }
  return 0;
}

おすすめ

転載: www.cnblogs.com/brucew-07/p/12147215.html