Lời giải trong đề bài
Đối với giữ gìn “Nào đó nguyên tố chi gian cần thiếtDán dánLiền nhau” như vậy vấn đề, có thể suy xét sử dụng một loại gọi là PQTree kết cấu tới giữ gìn.
PQTree thượng điểm có ba loại loại hình:
- Lá cây giao điểm,Tỏ vẻ một cái nguyên tố
- P loại tiết điểm,Tỏ vẻ cái này tiết điểm nhi tử trình tự là có thể tùy ý bài bố
- Q loại tiết điểm,Tỏ vẻ cái này tiết điểm nhi tử trình tự cần thiết là trước mặt cấp ra trình tự hoặc là nghịch tự
Hiện tại chúng ta suy xét như thế nào gia nhập một cái hạn chế. Thiết lúc này đây hạn chế là yêu cầu $S$ nội nguyên tố dán dán, như vậy chúng ta đem $S$ nội đối ứng lá cây đều đánh dấu thànhMàu đen,Đem mặt khác lá cây đánh dấu thànhMàu trắng.Đối với phi diệp giao điểm, nếu nó tử thụ nội chỉ có một loại nhan sắc tiết điểm, như vậy nó nhan sắc cùng loại này nhan sắc tương đồng; nếu không cho rằng cái này điểm nhan sắc làMàu xám.
Chúng ta trước cầu ra mỗi cái điểm nhan sắc, sau đó suy xét như thế nào đi fix cái này hạn chế. Giả thiết chúng ta hiện tại ở suy xét $v$ tử thụ, chúng ta phân loại thảo luận một chút:
- Nếu $v$ không phải màu xám tiết điểm, như vậy phía dưới hạn chế đều đã thỏa mãn, trực tiếp phản hồi
Nếu $v$ là màu xám tiết điểm:
Nếu $v$ là P loại tiết điểm: Thiết $v$ ba loại nhan sắc nhi tử tập hợp phân biệt là $v_B,v_W,v_G$ ( Black,White,Gray)
- Nếu $|v_G| = 1$ thả $|v_B| = 0$: Tiếp tục đi fix $v_G$ nội nguyên tố, sau đó trực tiếp phản hồi là được.
- Nếu $|v_G| > 2$, hiển nhiên xuất hiện mâu thuẫn, vô giải.
- Còn lại tình huống: Suy xét chúng ta trước quét sạch $v$ nhi tử tập hợp, sau đó trước hướng $son_v$ trung gia nhập $v_W$ trung sở hữu tiết điểm, sau đó tân kiến một cáiQ loại tiết điểm$n_1$, hướng $son_v$ trung gia nhập $n_1$. Sau đó trước gia nhập $v_G$ đến $son_{n_1}$, sau đó ở $son_{n_1}$ trung gian cắm vào một cái tân kiếnP loại tiết điểm$n_2$, sau đó lệnh $son_{n_2} = v_B$ là được. Chúng ta phát hiện nơi này yêu cầu hạn chế này hai cái màu xám tiết điểm màu trắng tất cả tại bên trái, màu đen tất cả tại phía bên phải ( hoặc tương phản ), chúng ta giả thiết hiện tại có một cái phân liệt hàm số, có thể đem cái này tử thụ điểm phân liệt thành hắc bạch bộ phận, cũngĐồng thời giữ lại sở hữu khả năng,Phân liệt thành tử thụ tiết điểm. Chúng ta chỉ cần đem $v_G$ trung điểm đổi thành đối ứng vector thì tốt rồi.
Nếu $v$ là Q loại tiết điểm:
- Tìm được nhất bên trái cùng nhất bên phải phi màu trắng tiết điểm vị trí $l,r$, vị trí chỉ chính là $son_v$ tương đối vị trí đánh số.
- Nếu $[l+1,r-1]$ nội có phiMàu đenTiết điểm, vô giải.
- Nếu không có màu đen tiết điểm, chỉ có một cái màu xám tiết điểm, đệ quy fix cái này màu xám tiết điểm sau đó phản hồi.
- Nếu không chỉ cần đem $l,r$ vị trí tiết điểm xem tình huống phân liệt ( chỉ có màu xám yêu cầu phân liệt ).
Cho nên hiện tại trọng điểm là như thế nào thực hiện cái này phân liệt hàm số $v$, WLOG, chúng ta muốn đem $v$ phân liệt thành bên trái tất cả đều là màu trắng, bên phải tất cả đều là màu đen rừng rậm. Hơn nữa chúng ta không thể mất đi sở hữu khả năng trình tự quan hệ ( cho nên trực tiếp mở ra là không thể ), căn cứ mặt trên quá trình dẫn dắt có thể được đến cùng loại quá trình:
- Nếu $v$ không phải màu xám tiết điểm, trực tiếp phản hồi trước mặt tử thụ.
Nếu $v$ là màu xám tiết điểm:
Nếu $v$ là P loại tiết điểm: Thiết $v$ ba loại nhan sắc nhi tử tập hợp phân biệt là $v_B,v_W,v_G$ ( Black,White,Gray)
- Nếu $|v_G| > 1$, hiển nhiên vô giải.
- Nếu không chúng ta nhất định là hình như, bên trái là một đống không có trình tự quan hệ hạn chế $v_W$ nội điểm, trung gian có thể là một cái $v_G$, sau đó bên phải là không có trình tự quan hệ hạn chế $v_B$ trung điểm. Cho nên chúng ta trước tân kiến hai cáiP loại tiết điểm$n_1,n_2$, $son_{n_1} = v_W,son_{n_2} = v_B$, sau đó lại đệ quy xử lý $v_G$ phân liệt tình huống ( nếu có lời nói ), cuối cùng dựa theo trình tự hợp lại thì tốt rồi. Cuối cùng không cần quên xóa bỏ tiết điểm $v$.
Nếu $v$ là Q loại tiết điểm:
- Nếu không tồn tại một loại trình tự ( chính tự cùng phản tự ), thỏa mãn bài bố hình thức hình như bạch - hôi - hắc, hiển nhiên vô giải.
- Nếu màu xám điểm số lượng $>1$, hiển nhiên vô giải.
- Nếu không chúng ta chỉ cần đệ quy phân liệt màu xám tiết điểm là được.
- Cuối cùng không cần quên xóa bỏ $v$ điểm
Phân tích một chút phức tạp độ: Giả thiết có $n$ cái nguyên tố, $m$ thứ thao tác. Thoạt nhìn chúng ta mỗi lần yêu cầu tân kiến rất nhiều tiết điểm, phức tạp độ sẽ tự bế. Nhưng là chú ý tới chúng ta có thể súc lên sở hữu liên ( rất nhiều về thụ phức tạp độ dùng thu nhỏ lại độ điểm cùng liên, hoàn thực dùng tốt ), như vậy bởi vì lá cây vĩnh viễn chỉ có $n$ cái, như vậy phi lá cây tiết điểm số lượng cũng là $O(n)$ ( trên thực tế sẽ có $n-1$ cái ), phức tạp độ chính là $O(nm)$.
Cụ thể thực hiện súc liên thời điểm, chúng ta dùng một cái dfs, mỗi lần đối với $v$ sở hữu nhi tử, đều vẫn luôn nhảy xuống đến cái thứ nhất không phải liên vị trí, cũng đưa bọn họ tất cả đều súc lên. Như vậy khả năng sẽ xử lý không tốt căn liền ra một cái liên, nhưng là có thể đặc phán ( tuy rằng ta số hiệu không phán )
Số hiệu
#include <bits/stdc++.h>
#define fi first
#define se second
#define DB double
#define U unsigned
#define P std::pair
#define LL long long
#define LD long double
#define pb emplace_back
#define MP std::make_pair
#define SZ(x) ((int)x.size())
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int MAXN = 1e5 + 5;
int typ[MAXN],col[MAXN];
std::vector<int> G[MAXN];
int bin[MAXN],tp,tot;
int n,m;
inline void run(){
puts( "-1" );
exit(0);
}
inline int New(int o){
int v = tp? bin[tp--]: ++tot;
typ[v] = o;return v;
}
inline void del(int v){
G[v].clear();bin[++tp] = v;
}
inline bool chk(std::vector<int> &vec){
int ps = -1;
FOR(i,0,SZ(vec)-1) if(col[vec[i]] == 2){
if(ps!= -1) return 0;
ps = i;
}
if(ps == -1){
FOR(i,0,SZ(vec)-1) if(col[vec[i]]){ps = i;break;}
}
FOR(i,0,ps-1) if(col[vec[i]]!= 0) return 0;
FOR(i,ps+1,SZ(vec)-1) if(col[vec[i]]!= 1) return 0;
return 1;
}
inline std::vector<int> split(int v){// tả 0 hữu 1
if(col[v] <= 1) return {v};
if(typ[v]){// Q
if(!chk(G[v])) std::reverse(all(G[v]));
if(!chk(G[v])) run();
std::vector<int> res;
for(auto x:G[v]){
if(col[x]!= 2) res.pb(x);
else{
std::vector<int> tmp = split(x);
res.insert(res.end(),all(tmp));
}
}
del(v);
return res;
}
else{// P
std::vector<int> son[3];
for(auto x:G[v]) son[col[x]].pb(x);
if(SZ(son[2]) > 1) run();
std::vector<int> res;
if(SZ(son[0])){
int n0 = New(0);G[n0] = son[0];
res.pb(n0);
}
if(SZ(son[2])){
std::vector<int> tmp = split(son[2][0]);
res.insert(res.end(),all(tmp));
}
if(SZ(son[1])){
int n1 = New(0);G[n1] = son[1];
res.pb(n1);
}
del(v);
return res;
}
}
inline void work(int v){
if(col[v] <= 1) return;
if(typ[v]){// Q
int l = 1e9,r = -1e9;
FOR(i,0,SZ(G[v])-1) if(col[G[v][i]]) l = std::min(l,i),r = std::max(r,i);
FOR(i,l+1,r-1) if(col[G[v][i]]!= 1) run();
if(l == r && col[G[v][l]] == 2){
work(G[v][l]);
return;
}
std::vector<int> son;
FOR(i,0,l-1) son.pb(G[v][i]);
if(col[G[v][l]] == 2){
std::vector<int> tmp = split(G[v][l]);
son.insert(son.end(),all(tmp));
}
else son.pb(G[v][l]);
FOR(i,l+1,r-1) son.pb(G[v][i]);
if(l!= r){
if(col[G[v][r]] == 2){
std::vector<int> tmp = split(G[v][r]);
std::reverse(all(tmp));
son.insert(son.end(),all(tmp));
}
else son.pb(G[v][r]);
}
FOR(i,r+1,SZ(G[v])-1) son.pb(G[v][i]);
G[v] = son;
}
else{// P
std::vector<int> son[3];
for(auto x:G[v]) son[col[x]].pb(x);
if(son[1].empty() && SZ(son[2]) == 1){
work(son[2][0]);
return;
}
G[v].clear();
if(SZ(son[2]) > 2) run();
G[v] = son[0];
int n1 = New(1);G[v].pb(n1);
if(SZ(son[2]) >= 1){
std::vector<int> tmp = split(son[2][0]);
G[n1].insert(G[n1].end(),all(tmp));
}
if(SZ(son[1])){
int n2 = New(0);
G[n1].pb(n2);
G[n2] = son[1];
}
if(SZ(son[2]) >= 2){
std::vector<int> tmp = split(son[2][1]);
std::reverse(all(tmp));
G[n1].insert(G[n1].end(),all(tmp));
}
}
}
char str[MAXN];
inline void apply(int v){
if(v >= 2 && v <= m+1){
col[v] = (str[v-1]=='1');
return;
}
int c0 = 0,c1 = 0;
for(auto x:G[v]){
apply(x);
if(col[x] == 0) c0 = 1;
else if(col[x] == 1) c1 = 1;
else c0 = c1 = 1;
}
if(c0 &&!c1) col[v] = 0;
else if(!c0 && c1) col[v] = 1;
else col[v] = 2;
}
inline void gao(int v){
for(auto &x:G[v]){
int t = x;
while(SZ(G[t]) == 1){
int p = t;
t = G[t][0];
del(p);
}
x = t;gao(x);
}
}
inline void dfs(int v){
if(v >= 2 && v <= m+1){
printf( "%d",v-1);
return;
}
for(auto x:G[v]) dfs(x);
}
int main(){
scanf( "%d%d",&n,&m);
int rt = New(0);
FOR(i,1,m) G[rt].pb(New(0));
FOR(i,1,n){
scanf( "%s",str+1);
apply(rt);
work(rt);
gao(rt);
}
dfs(rt);puts( "" );
return 0;
}