BZOJ4078 : [Wf2014]Metal Processing Plant

设$D(A)\leq D(B)$,从小到大枚举$D(A)$,双指针从大到小枚举$D(B)$。

那么对于权值不超过$D(A)$的边,可以忽略。

对于权值介于$(D(A),D(B)]$之间的边,需要满足那两个点不能都在集合$A$。

对于权值大于$D(B)$的边,需要满足那两个点不在同一个集合。

所以建图判断2-SAT是否有解即可,这可以使用压位Kosaraju算法。

时间复杂度$O(\frac{n^4}{64})$。

 

#include<cstdio>
#include<algorithm>
#define N 205
using namespace std;
typedef unsigned long long ll;
int n,m,i,j,k,t,q[N<<1],f[N<<1],ans;
struct E{int x,y,w;E(){}E(int _x,int _y,int _w){x=_x,y=_y,w=_w;}}e[N*N];
inline bool cmp(const E&a,const E&b){return a.w<b.w;}
struct BIT{
  ll v[4];
  void clear(){for(int i=0;i<4;i++)v[i]=0;}
  void flip(int x){v[x>>6]^=1ULL<<(x&63);}
  int get(int x){return v[x>>6]>>(x&63)&1;}
}v0,v1,g0[N<<1],g1[N<<1];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void addA(int x,int y){
  g0[x].flip(y);
  g1[y+n].flip(x);
  g0[y].flip(x);
  g1[x+n].flip(y);
}
inline void addB(int x,int y){
  g0[x+n].flip(y);
  g1[y].flip(x);
  g0[y+n].flip(x);
  g1[x].flip(y);
}
void dfs1(int x){
  if(x<n){
    v0.flip(x);
    for(int i=0;i<4;i++)while(1){
      ll o=v1.v[i]&g0[x].v[i];
      if(!o)break;
      dfs1((i<<6|__builtin_ctzll(o))+n);
    }
  }else{
    v1.flip(x-n);
    for(int i=0;i<4;i++)while(1){
      ll o=v0.v[i]&g0[x].v[i];
      if(!o)break;
      dfs1(i<<6|__builtin_ctzll(o));
    }
  }
  q[++t]=x;
}
void dfs2(int x,int y){
  f[x]=y;
  if(x<n){
    v0.flip(x);
    for(int i=0;i<4;i++)while(1){
      ll o=v1.v[i]&g1[x].v[i];
      if(!o)break;
      dfs2((i<<6|__builtin_ctzll(o))+n,y);
    }
  }else{
    v1.flip(x-n);
    for(int i=0;i<4;i++)while(1){
      ll o=v0.v[i]&g1[x].v[i];
      if(!o)break;
      dfs2(i<<6|__builtin_ctzll(o),y);
    }
  }
}
inline bool check(){
  int i;
  v0.clear(),v1.clear();
  for(i=0;i<n;i++)v0.flip(i),v1.flip(i);
  for(t=i=0;i<n;i++)if(v0.get(i))dfs1(i);
  for(i=0;i<n;i++)if(v1.get(i))dfs1(i+n);
  for(i=0;i<n;i++)v0.flip(i),v1.flip(i);
  for(i=t;i;i--)if(q[i]<n){if(v0.get(q[i]))dfs2(q[i],q[i]);}else if(v1.get(q[i]-n))dfs2(q[i],q[i]);
  for(i=0;i<n;i++)if(f[i]==f[i+n])return 0;
  return 1;
}
void solve(){
  ans=~0U>>1;
  sort(e+1,e+m+1,cmp);
  for(i=0;i<n+n;i++)g0[i].clear(),g1[i].clear();
  for(i=1;i<=m;i++)addA(e[i].x,e[i].y);
  for(i=0,j=m;i<=j;i++){
    if(i)addA(e[i].x,e[i].y);
    while(e[i].w+e[j].w>=ans||check()){
      ans=min(ans,e[i].w+e[j].w);
      if(j)addB(e[j].x,e[j].y);
      if((--j)<i)return;
    }
  }
}
int main(){
  while(~scanf("%d",&n)){
    for(m=i=0;i<n;i++)for(j=i+1;j<n;j++)read(k),e[++m]=E(i,j,k);
    solve();
    printf("%d\n",ans);
  }
  return 0;
}

  

posted @ 2016-10-26 09:17  Claris  阅读(488)  评论(0编辑  收藏  举报