代碼是昨天寫的,今天又試着做重複覆蓋的DLX,發現根本寫不下,出現了重重錯誤,我還以爲我昨天誤打誤撞的代碼很優咧,太自以爲是了!這道HDOJ2828也是好題,它比我今天試寫的HDOJ3957簡單得多,最大的不同不是一個只是求一個YES/NO,另一個求的是最小dfs深度,而是3957的鏈表數據中的關係比2828複雜,所以dance實現部分的思想都是不一樣的~
**尚未成功,菜鳥仍需努力~不想說revolution那個凝重的詞。
// 第二個Dancing links,1Y,0ms,暫時排名第五,挺興奮的!
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int NN=505;
const int MM=51000;
int n,m,cnt,R[MM],L[MM],U[MM],D[MM],C[MM],H[MM],flag[MM];
int S[NN],O[NN],V[NN];
void init()//這裏的十字鏈表以燈爲列,開關爲行
{
cnt=n;
for (int i=0; i<=n; i++)
{
D[i]=U[i]=i;
R[i]=i+1;
L[i+1]=i;
S[i]=0;
}
L[0]=n,R[n]=0;
for (int i=1; i<=m; i++) V[i]=0;
}
void add_link(int i,int j,int t)
{
C[++cnt]=i;
H[cnt]=j;
S[i]++;
flag[cnt]=t; //開關狀態
D[cnt]=i;
U[cnt]=U[i];
if (V[j]) R[cnt]=V[j],L[cnt]=L[V[j]];
else R[cnt]=L[cnt]=cnt;
V[j]=cnt;
U[D[cnt]]=cnt;
D[U[cnt]]=cnt;
R[L[cnt]]=cnt;
L[R[cnt]]=cnt;
}
void remove(int c)//題意不同,這裏remove有變,指的是刪除c列
{
L[R[c]]=L[c];
R[L[c]]=R[c];
for (int i=D[c]; i!=c; i=D[i])
{
L[R[i]]=L[i];
R[L[i]]=R[i];
S[C[i]]--;
}
}
void resume(int c)
{
for (int i=U[c]; i!=c; i=U[i])
{
R[L[i]]=i;
L[R[i]]=i;
S[C[i]]++;
}
R[L[c]]=L[R[c]]=c;
}
bool dance()
{
if (!R[0])
{
for (int i=1; i<m; i++) printf(O[i]==1?"ON ":"OFF ");
puts(O[m]==1?"ON":"OFF");
return 1;
}
int c,s=MM,i,j;
for (i=R[0]; i; i=R[i]) if (S[i]<s) s=S[c=i];
if (s==0) return 0; //s==0說明沒有開關能使燈c處於ON的狀態了
R[L[c]]=R[c]; L[R[c]]=L[c]; //這裏只需刪去列指針c即可
for (i=D[c]; i!=c; i=D[i])
{
O[H[i]]=flag[i];//記錄答案
for (int j=R[i]; j!=i; j=R[j])
{
if (flag[j]==flag[i]) remove(C[j]);
else D[U[j]]=D[j],U[D[j]]=U[j],S[C[j]]++;//這裏沒寫S[C[j]]--時也過了,想想確實不影響正確性
}
if (dance()) return 1;
for (int j=L[i]; j!=i; j=L[j])
{
if (flag[j]==flag[i]) resume(C[j]);
else U[D[j]]=j,D[U[j]]=j,S[C[j]]--;
}
}
R[L[c]]=c; L[R[c]]=c;//恢復列指針c
return 0;
}
int main()
{
int k,x;
char str[5];
while (~scanf("%d%d",&n,&m))
{
init();
for (int i=1; i<=n; i++)
{
scanf("%d",&k);
while (k--)
{
scanf("%d%s",&x,&str);
if (str[1]=='N') add_link(i,x,1);
else add_link(i,x,0);
}
}
if (!dance()) puts("-1");
}
return 0;
}