[搜索] ICPC 2016 Qingdao J & HDU 5991 Cliques

给你一个图,你可以执行删边或者加边这样的操作,然后将这个图变成若干个团,问最小的步数。
如果答案超过10,输出-1。

dls orzz

这里写图片描述
这里写图片描述

想偷懒用set 结果T了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
#define read(x) scanf("%d",&(x))
using namespace std;

const int N=105;

int n;

inline int Tri(int _a,int _b,int _c){
  int a=min(_a,min(_b,_c)),c=max(_a,max(_b,_c)),b=_a^_b^_c^a^c;
  return (a-1)*n*n+(b-1)*n+c-1;
}

struct SS{
  int tot,a[N*N*N],pos[N*N*N];
  void insert(int x){ a[++tot]=x; pos[x]=tot; }
  void erase(int x){ pos[a[tot]]=pos[x]; a[pos[x]]=a[tot]; tot--; }
  bool empty(){ return tot==0; }
  void clear(){ tot=0; }
}Set;

int Map[N][N];
#define T (Map[i][j]+Map[j][k]+Map[i][k])
inline void Add(int i,int j,int k){
  if (T==2) Set.insert(Tri(i,j,k));
}
inline void Del(int i,int j,int k){
  if (T==2) Set.erase(Tri(i,j,k));
}
inline void Rev(int i,int j){
  for (int k=1;k<=n;k++) if (k!=i && k!=j) Del(i,j,k);
  Map[i][j]^=1; Map[j][i]^=1;
  for (int k=1;k<=n;k++) if (k!=i && k!=j) Add(i,j,k);
}

int ans;

inline void dfs(int st){
  if (Set.empty()) ans=min(ans,st-1);
  if (st>=ans) return;
  int t=Set.a[1],c=t%n+1,b=t/n%n+1,a=t/n/n+1;
  Rev(a,b); dfs(st+1); Rev(a,b);
  Rev(b,c); dfs(st+1); Rev(b,c);
  Rev(a,c); dfs(st+1); Rev(a,c);
}

int main(){
  int TT,Case=0;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(TT);
  while (TT--){
    read(n);
    for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) read(Map[i][j]);
    for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) for (int k=j+1;k<=n;k++) Add(i,j,k);
    ans=11;
    dfs(1);
    printf("Case #%d: %d\n",++Case,ans==11?-1:ans);
    Set.clear();
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值