Codeforces 1250E The Coronation

Problem-solving ideas

2-SAT with the idea of the subject into: known \ (n-\) th tuple \ (<X, Y> \) , can calculate the number of elements belonging to different tuple \ ((a, b) \) there is a conflict, to each tuple \) \ (<x, y > select a selected element selected from less as possible and \ (Y \) , and asked whether to select \ (n-\) th pairwise conflicting elements, when the selected program can be output.

Can be obtained through simple derivation for \ (<x_i, y_i> \ ) and \ (<x_j, y_j> \ )

  • If \ (x_ix_j \) (not) conflict, \ (y_iy_j \) (not) conflict
  • If \ (x_iy_j \) (not) conflict, \ (y_ix_j \) (not) conflict

Continue to use the idea of ​​2-SAT, and the binding properties of the above:

  • If \ (x_i \) only and \ (x_j \) conflict, from the \ (x_i \) to \ (y_j \) connected to an edge from \ (x_j \) to \ (y_i \) connected to one side;
  • If \ (x_i \) only and \ (y_j \) conflict, from the \ (x_i \) to \ (x_j \) connected to an edge from \ (y_i \) to \ (y_j \) connected to one side;
  • Not even if they will not conflict sides;
  • If no solution can conflict.

In this way, we obtain one or more blocks of China Unicom, according to the nature of the previous derivation, for the first \ (I \) bins and, if \ (I \) selection method determined, then the same block in the Unicom select the method are also determined, together with China Unicom among the different blocks are independently of each other, we only need to select each greedy Unicom block \ (y \) less the program, then the answer to all blocks plus Unicom it is the ultimate answer.

Tarjan shrink or run the point and check point of constriction look no maintenance.

AC Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=110;
int n,m,k;
ll a[55],b[55]; char s[55];

int fa[N],sz[N]; bool vis[N];
int find(int x){return fa[x]==x?x:(fa[x]=find(fa[x]));}
void merge(int x,int y){
    x=find(x); y=find(y);
    if(x!=y){sz[y]+=sz[x];fa[x]=y;} 
}

inline int getsame(ll x){
    int cnt=0;
    while(x){cnt++;x-=x&(-x);}
    return m-cnt;   
}

void solve(){
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            bool c1=false,c2=false;
            if(getsame(a[i]^a[j])>=k)c1=true;
            if(getsame(a[i]^b[j])>=k)c2=true;
            if(c1 && c2)continue;
            if(!c1 && !c2){printf("-1\n");return;}
            if(c2)merge(i,j+n),merge(i+n,j);
            if(c1)merge(i,j),merge(i+n,j+n);
        }
    }
    vector<int>ans;
    for(int i=1;i<=n;i++){
        if(find(i)==find(i+n)){printf("-1\n");return;}
        int fi=find(i),fin=find(i+n);
        if(vis[fi])continue;
        if(vis[fin]){ans.push_back(i);continue;}
        if(sz[fi]>sz[fin]){vis[fin]=true;ans.push_back(i);}
        else vis[fi]=true;
    }
    printf("%d\n",(int)ans.size());
    for(int i:ans)printf("%d ",i); puts("");
}

int main()
{   
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&n,&m,&k);
        for(int i=1;i<=2*n;i++)fa[i]=i, sz[i]=(i>n?1:0), vis[i]=false;  
        for(int i=1;i<=n;i++){
            scanf("%s",s); a[i]=0; b[i]=0;
            for(int j=0;s[j];j++)a[i]*=2, a[i]+=s[j]-'0';
            reverse(s,s+m);
            for(int j=0;s[j];j++)b[i]*=2, b[i]+=s[j]-'0';
        }
        solve();
    }
    return 0;   
}

Guess you like

Origin www.cnblogs.com/zengzk/p/11774349.html