F - True Liars POJ 1417(并查集)(DFS)

来源:互联网 发布:政务软件 编辑:程序博客网 时间:2024/06/05 22:34

我的天!!做这道题发现两个重要的坑点!

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;} 


0 0
原创粉丝点击