Jurassic Remains [Meet Midway]

Paleontologists in Siberia have recently found a number of fragments of Jurassic period dinosaur skeleton. The paleontologists have decided to forward them to the paleontology museum. Unfortunately, the dinosaur was so huge, that there was no box that the fragments would fit into. Therefore it was decided to split the skeleton fragments into separate bones and forward them to the museum where they would be reassembled. To make reassembling easier, the joints where the bones were detached from each other were marked with special labels. Meanwhile, after packing the fragments, the new bones were found and it was decided to send them together with the main fragments. So the new bones were added to the package and it was sent to the museum. 

However, when the package arrived to the museum some problems have shown up. First of all, not all labels marking the joints were distinct. That is, labels with letters 'A' to 'Z' were used, and each two joints that had to be connected were marked with the same letter, but there could be several pairs of joints marked with the same letter. 

Moreover, the same type of labels was used to make some marks on the new bones added to the box. Therefore, there could be bones with marked joints that need not be connected to the other bones. The problem is slightly alleviated by the fact that each bone has at most one joint marked with some particular letter. 

Your task is to help the museum workers to restore some possible dinosaur skeleton fragments. That is, you have to find such set of bones, that they can be connected to each other, so that the following conditions are true: 
If some joint is connected to the other joint, they are marked with the same label. 
  • For each bone from the set each joint marked with some label is connected to some other joint. 
  • The number of bones used is maximal possible.

Note that two bones may be connected using several joints.

Input

The first line of the input contains N -- the number of bones (1 <= N <= 24). Next N lines contain bones descriptions: each line contains a non-empty sequence of di#erent capital letters, representing labels marking the joints of the corresponding bone.

Output

On the first line of output print L -- the maximal possible number of bones that could be used to reassemble skeleton fragments. Then print on the next line L integer numbers in ascending order -- the bones to be used. Bones are numbered starting from one, as they are given in the input.

Sample Input

6
ABD
EG
GE
ABE
AC
BCD

Sample Output

5
1 2 3 5 6
The main idea: Jurassic. Given a string of n uppercase letters. Choose as many strings as possible so that each capital letter can appear even times. 

Analysis: In a string, the number of occurrences of each character is irrelevant, the important thing is the parity of these times, so I thought of using a binary bit to represent a letter (1 means odd occurrences, 0 means even occurrences).
  The sample is written in binary and is
    ABCDEFGH
    1 1 0 1 0 0 0 0 ABD
    0 0 0 0 1 0 1 0 EG
    0 0 0 0 1 0 1 0 GE
    1 1 0 0 1 0 0 0 ABE
    1 0 1 0 0 0 0 0 AC
    0 1 1 1 0 0 0 0 BCD

  problems are converted to find as many numbers as possible, so that their xor value is 0. The
  exhaustive method will time out. Note that the two integers whose xor value is 0 must be completely equal, and the string can be divided into two parts: first calculate all the xor values ​​that can be obtained by the first n / 2 strings, and save them to a mapping S (xor Value a subset of the first n / 2 strings); then enumerate all the xor values ​​that can be obtained after the n / 2 strings, and search in S every time.
  If the mapping is implemented by STL map, the total time complexity is O (2

n/2

logn), this method is called the midway encounter method.
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cmath>
#include<cstring>
#include <algorithm>
#include <queue>
#include<map>
using namespace std;
typedef long long LL;
const LL INF = 1e13;
const int mod = 1000000007;
const int mx = 27; //check the limits, dummy
typedef pair<int, int> pa;
//const double PI = acos(-1);
//ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
#define swa(a,b) a^=b^=a^=b
#define re(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define rb(i,a,b) for(int i=(b),_=(a);i>=_;i--)
#define clr(a) memset(a, 0, sizeof(a))
#define lowbit(x) ((x)&(x-1))
//#define mkp make_pai
//void sc(int& x) { scanf("%d", &x); }void sc(int64_t& x) { scanf("%lld", &x); }void sc(double& x) { scanf("%lf", &x); }void sc(char& x) { scanf(" %c", &x); }void sc(char* x) { scanf("%s", x); }
int n, m, k,ans;
int a[mx];
map<int, int>table;
int bitcnt(int x) {
    return x == 0 ? 0 : bitcnt(x / 2) + (x & 1);
}
char s[1000];
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T, cas = 1;
    
    while (cin>>n&&n)
    {
        re(i, 0, n) {//Enter and calculate the bit vector corresponding to each string 
            cin >> s; 
            a [i] = 0 ;
             for ( int j = 0 ; s [j]! = ' \ 0 ' ; j ++ ) 
            { 
                a [i] ^ = ( 1 << (s [j]- ' A ' )); 
            } 
        } 
        // Calculate the xor value of all subsets of the first n1 elements
         // table [x] stores the xor value of x, and the bitcount is as large as possible Subset of 
        table.clear ();
         int n1 = n / 2 , n2 = n- n1; 
        re (i, 0, 1 << n1) {
             int x = 0 ; 
            re (j, 0 , n1)
                 if (i & ( 1 << j)) x ^ = a [j];
             if (! Table.count (x) || bitcnt (table [x]) < bitcnt (i)) 
                table [x] = i; 
        } 
        // Enumerate all subsets of n2 elements after enumeration, and find 
        int ans = 0 in the table ; 
        re (i, 0 , 1 << n2) {
             int x = 0 ; 
            re (j, 0, n2)
                if (i & (1 << j))x ^= a[n1 + j];
            if (table.count(x) && bitcnt(ans) < bitcnt(table[x]) + bitcnt(i))
                ans = (i << n1) ^ table[x];
        }
        cout << bitcnt(ans) << endl;
        re(i, 0, n)
            if (ans & (1 << i))
                cout << i + 1 << ' ';
        cout << endl;
    }
    return 0;
}                

 

Reference from https://www.cnblogs.com/acm-bingzi/p/3330852.html
 

Guess you like

Origin www.cnblogs.com/xxxsans/p/12739736.html