我的天!!做这道题发现两个重要的坑点!
1、 memset只能用于初始化数组的0和-1或者是16进制的比如0x3f3f3f3f;
2、字符数组越界了会影响后面变量的值!
好吧,搞了半天先是wa了好几发,最后超时了,过程中修复好多bug,能写出还是。。费了不少功夫,太弱了!
心累,mdzz!
查了发现是要用并查集加dp做,我的天!也可能是我的DFS优化不够,先存个代码过会再看吧。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e4+5;
int father[maxn],Rank[maxn],sum[maxn][3],vis[maxn][2],cnt,vv[maxn][2],summ[maxn][2];
int query(int x) { //路径压缩
if(father[x] != x) {
int per = father[x];
father[x] = query(father[x]);
Rank[x] = (Rank[x] + Rank[per] + 2) %2;
}
return father[x];
}
void dfs(int sum1,int sum2,int i,int x,int y,int cc) { //dfs查有几种可行方案,如果只有唯一解,那么就是可行的,否则输出no
//printf("%d-%d-%d-%d-%d-%d\n",sum1,sum2,i,x,y,cc);
if(sum1 > x || sum2 > y)
return ;
if(sum1 == x && sum2 == y) {
//printf("tt\n");
cnt++;
if(cnt == 1){
for(int i = 1;i <= cc;i++)
vv[i][0] = vis[i][0];
}
return ;
}
if(cnt > 1 || i > (cc))
return ;
int t = sum1 + sum[i][0];
int tt = sum2 + sum[i][1];
if(!vis[i][0]) {
vis[i][0] = 1;
i++;
//printf("%d-%d-%d-%d-%d\n",t,tt,i,x,y,cc);
dfs(t,tt,i,x,y,cc);
i--;
vis[i][0] = 0; // 每次检查先标记,回溯的时候再消除标记。
}
int j = sum1 + sum[i][1];
int jj = sum2 + sum[i][0];
if(!vis[i][1]) {
//printf("%d=%d=%d=%d=%d\n",j,jj,i,x,y,cc);
vis[i][1] = 1;
i++;
dfs(j,jj,i,x,y,cc);
i--;
vis[i][1] = 0;
}
}
int main() {
//freopen("haha.txt","r",stdin);
int m,nx,ny;
while(~scanf("%d%d%d",&m,&nx,&ny) && (m || ny || nx)) {
int x,y;
if(nx == ny) {
char str[20];
for(int i = 1;i <= m;i++)
scanf("%d%d%s",&x,&y,str);
printf("no\n");
continue;
}
int n = (nx + ny);
char str[20]; //开字符数组的时候要记得开大一些
for(int i = 0;i <= n;i++) {
Rank[i] = 0;
father[i] = i;
}
for(int i = 1;i <= m;i++) {
scanf("%d%d%s",&x,&y,str);
int a = query(x);
int b = query(y);
if(a != b) {
father[b] = a;
if(str[0] == 'y')
Rank[b] = (Rank[x] - Rank[y] + 2) % 2;
else if(str[0] == 'n')
Rank[b] = (Rank[x] - Rank[y] + 3) % 2;
}
}
memset(summ,0,sizeof(summ)); //memset只能用于16进制和0或者-1
memset(sum,0,sizeof(sum));
memset(vis,0,sizeof(vis));
for(int i = 1;i <= n;i++) {
int zz = query(i);
if(!Rank[i])
summ[zz][0]++;
else
summ[zz][1]++;
}
int cc = 0;
for(int i = 1;i <= n;i++) {
if(summ[i][0] || summ[i][1]) {
sum[++cc][0] = summ[i][0];
sum[cc][1] = summ[i][1];
sum[cc][2] = i;
}
}
cnt = 0;
dfs(0,0,1,nx,ny,cc);
//printf("%d=",cnt);
if(cnt == 1) {
int nn[2005],sss = 0;
for(int i = 1;i <= cc;i++) { //按顺序输出善良的人的编号
if(vv[i][0]) {
for(int j = 1;j <= n;j++) {
if(query(j) == sum[i][2] && !Rank[j])
nn[sss++] = j;
}
}
else {
for(int j = 1;j <= n;j++) {
if(query(j) == sum[i][2] && Rank[j])
nn[sss++] = j;
}
}
}
sort(nn,nn+sss);
for(int i = 0;i < sss;i++)
printf("%d\n",nn[i]);
printf("end\b");
}
else
printf("no\n");
/*for(int i = 1;i <= cc;i++)
printf("%d-%d ",sum[i][0],sum[i][1]);
printf("\n");*/
}
return 0;
}