1 条题解

  • 0
    @ 2026-1-29 20:50:08

    D41 2-SAT P3513 [POI2011] KON-Conspiracy

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=5005,M=N<<1;
    int head[M],idx;
    struct edge{int to,ne;}e[N*N];
    int dfn[M],low[M],tim,stk[M],top,scc[M],cnt;
    int n,m;
    int a[N],an;      //存储后勤成员与数量
    int b[N],bn;      //存储同谋成员与数量
    int num[N],id[N]; //存储矛盾点的数量与编号
    bool know[N][N],inb[N]; //是否认识,是否在同谋组
    
    void add(int x,int y){
      e[++idx]={y,head[x]};
      head[x]=idx;
    }
    void tarjan(int x){
      dfn[x]=low[x]=++tim;
      stk[++top]=x;
      for(int i=head[x];i;i=e[i].ne){
        int y=e[i].to;
        if(!dfn[y]){ //若y尚未访问
          tarjan(y);
          low[x]=min(low[x],low[y]);
        }
        else if(!scc[y]) //若y已访问且未处理
          low[x]=min(low[x],dfn[y]);
      }
      
      if(low[x]==dfn[x]){ //若x是SCC的根
        ++cnt;
        for(int y=-1;y!=x;)
          scc[y=stk[top--]]=cnt;
      }
    }
    int main(){
      scanf("%d",&n);
      for(int i=1,x;i<=n;i++){
        scanf("%d",&m);
        while(m--) scanf("%d",&x),know[i][x]=true;
      }
      for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
          if(know[i][j]) add(i+n,j),add(j+n,i);
          else add(i,j+n),add(j,i+n);
        }
      for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i);
      
      for(int i=1;i<=n;i++){
        if(scc[i]==scc[i+n]) puts("0"),exit(0);
        if(scc[i]<scc[i+n]) a[++an]=i; //存储后勤成员
        else b[++bn]=i,inb[i]=1;       //存储同谋成员
      }
      for(int i=1;i<=an;i++)
        for(int j=1;j<=bn;j++)
          if(know[a[i]][b[j]]) //后勤认识同谋即矛盾点
            ++num[a[i]],id[a[i]]=b[j];
      for(int i=1;i<=bn;i++)
        for(int j=1;j<=an;j++)
          if(!know[b[i]][a[j]]) //同谋不认识后勤即矛盾点
            ++num[b[i]],id[b[i]]=a[j];
      int ans=0;
      for(int i=1;i<=n;i++){
        //i有1个矛盾点且i的矛盾点无矛盾点,可以直接交换
        if(num[i]==1 && !num[id[i]]) ++ans;
        //i无矛盾点且本组超过1人,可以直接移到对面组
        if(!num[i]&&((inb[i]&&bn>1)||(!inb[i]&&an>1))) ++ans;
      }
      if(an&&bn) ++ans; //初始解
      printf("%d\n",ans);
    }
    
    • 1

    D41 2-SAT「POI2011 R1」同谋者 Conspiracy

    信息

    ID
    3880
    时间
    3000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    6
    已通过
    2
    上传者