zoukankan      html  css  js  c++  java
  • POJ 1417 True Liars

    POJ连炸多日……

    题目

    岛上有两种人,一种只说假话,一种只说真话。给出两种人的数量和一些你问他们的问题(问A,B是不是说真话),问是否能确定每个人到底是说真话还是说假话。

    题解

    1.发现a,b相同会回答yes 否则回答no

    2.套用并查集模板 画图

    设边权:相同为0,不同为1

    猜(fav[fa1]=fav[a] ) xor ( fav[b] ;) xor ( d),枚举各种情况果然成立……

    3.得到一棵树

    其实中途会进行路径压缩……

    可以统计每棵树中与代表元素相同的个数(A[i])和不同的个数(B[i])(边权为1说明不同,为0说明相同)

    然后问题就转换成

    (n = 树的棵数)

    (X[i] = A[i];;;or;;;B[i];;;left( {1 le i le n} ight))

    (S[i] = left{ {egin{array}{*{20}{c}}
    {X[i]}&{i = 1}\
    {S[i - 1] + X[i]}&{2 le i le n}
    end{array}} ight.)

    问是否有且仅有1中选择方法使$S[n]=p1$

    刚开始用暴力枚举$O(2^n)$ 一定超时……

    犯的错误:

    注意统计每棵树的时候有可能会错,如

    如果按照没有访问根节点就……

    犯的错误
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #ifndef max
      5 #define max(a,b) ((a)>(b)?(a):(b))
      6 #endif
      7 #define REP(x,i,j) for(int x=i; x<j; x++)
      8 #define REPE(x,i,j) for(int x=i; x<=j; x++)
      9 #define MAXN 607
     10 using namespace std;
     11 int fa[MAXN];
     12 int fav[MAXN];
     13 int n,p,q;
     14 inline void initu() {
     15     REPE(i,0,n) {
     16         fa[i]=i;
     17         fav[i]=0;
     18     }
     19 }
     20 
     21 inline int findu(int x) {
     22     int t=x, p;
     23     int v=0,vt;
     24     while(t!=fa[t]) {
     25         v^=fav[t];
     26         t=fa[t];
     27     }
     28     while(x!=t) {
     29         vt =v;
     30         p=fa[x];
     31         fa[x]=t;
     32         v^=fav[x];
     33         fav[x]=vt;
     34         x=p;
     35     }
     36     return t;
     37 }
     38 
     39 //inline void uu(int x, int y, int d) {
     40 //    int a=findu(x), b=findu(y);
     41 //    int va=fav[x], vb=fav[y];
     42 //    fa[a]=b;
     43 //    fav[a]=va^vb^d;
     44 //}
     45 
     46 int main() {
     47     int a;
     48     while(~scanf("%d%d%d", &a, &p, &q) && (a || p || q)) {
     49         n=p+q;
     50         initu();
     51         REP(i,0,a) {
     52             int x,y;
     53             char s[4];
     54             scanf("%d%d%s", &x, &y, s);
     55             bool d = s[0]=='n';
     56             int a=findu(x), b=findu(y);
     57             if(a!=b) {
     58                 fa[a]=b;
     59                 fav[a]=fav[x]^fav[y]^d;
     60             }
     61         }
     62         if(p==q) {
     63             printf("no
    ");
     64         } else {
     65             bool gen[MAXN]; memset(gen,0,sizeof gen);
     66             int cnt[MAXN][2]; memset(cnt,0,sizeof cnt);
     67             int dp[MAXN][MAXN]; memset(dp,0,sizeof dp);
     68             int cntgen[MAXN]; memset(cntgen,0,sizeof cntgen);
     69             dp[0][0]=1;
     70             int ki = 0;
     71             REPE(i,1,n) {
     72                 int t = findu(i);
     73                 if(!gen[t]){ki++;gen[t]=true;cntgen[ki]=t;}
     74                 cnt[ki][fav[i]]++;
     75             }
     76             REPE(i,1,ki){
     77                 for(int j=p;j>=0;j--){
     78                     if(j-cnt[i][0]>=0&&dp[i-1][j-cnt[i][0]]){
     79                         dp[i][j]+=dp[i-1][j-cnt[i][0]];
     80                     }
     81                     if(j-cnt[i][1]>=0&&dp[i-1][j-cnt[i][1]]){
     82                         dp[i][j]+=dp[i-1][j-cnt[i][1]];
     83                     }
     84                 }
     85             }
     86             if(dp[ki][p]!=1) {
     87                 printf("no
    ");
     88                 continue;
     89             } else {
     90                 int ansarr[MAXN], ansarri = 0; memset(ansarr,0,sizeof ansarr);
     91                 for(int i=ki;i>=1;i--) {
     92                     if(p-cnt[i][0]>=0&&dp[i-1][p-cnt[i][0]]){
     93                         for(int j=1;j<=n;j++){
     94                             if(fa[j]==cntgen[i]&&fav[j]==0)ansarr[ansarri++]=j;
     95                         }
     96                         p-=cnt[i][0];
     97                     } else {
     98                         for(int j=1;j<=n;j++){
     99                             if(fa[j]==cntgen[i]&&fav[j]==1)ansarr[ansarri++]=j;
    100                         }
    101                         p-=cnt[i][1];
    102                     }
    103                 }
    104                 sort(ansarr,ansarr+ansarri);
    105                 REP(i,0,ansarri) {
    106                     printf("%d
    ", ansarr[i]);
    107                 }
    108                 printf("end
    ");
    109             }
    110         }
    111     }
    112     return 0;
    113 }
    WA代码

    后来抄了个DP,还不知道怎么分析:(

    还得多练DP:(

    设dp[i][j]为前i组人中说真话的人数为j这种情况的数量,很容易写出转移方程

    然后倒过来输出解(因为要判断到底是怎么转移过来的)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<map>
      5 #ifndef max
      6 #define max(a,b) ((a)>(b)?(a):(b))
      7 #endif
      8 #define REP(x,i,j) for(int x=i; x<j; x++)
      9 #define REPE(x,i,j) for(int x=i; x<=j; x++)
     10 #define MAXN 1007
     11 using namespace std;
     12 int fa[MAXN];
     13 int fav[MAXN];
     14 int n,p,q;
     15 
     16 bool gen[MAXN];      
     17 int cnt[MAXN][2];    
     18 int dp[MAXN][MAXN];  
     19 int cntgen[MAXN];    
     20 map<int,int> kitogen;
     21 inline void initu() {
     22     REPE(i,0,n) {
     23         fa[i]=i;
     24         fav[i]=0;
     25     }
     26 }
     27 
     28 inline int findu(int x) {
     29     int t=x, p;
     30     int v=0,vt;
     31     while(t!=fa[t]) {
     32         v^=fav[t];
     33         t=fa[t];
     34     }
     35     while(x!=t) {
     36         vt =v;
     37         p=fa[x];
     38         fa[x]=t;
     39         v^=fav[x];
     40         fav[x]=vt;
     41         x=p;
     42     }
     43     return t;
     44 }
     45 
     46 //inline void uu(int x, int y, int d) {
     47 //    int a=findu(x), b=findu(y);
     48 //    int va=fav[x], vb=fav[y];
     49 //    fa[a]=b;
     50 //    fav[a]=va^vb^d;
     51 //}
     52 
     53 int main() {
     54     int a;
     55     while(~scanf("%d%d%d", &a, &p, &q) && (a || p || q)) {
     56         n=p+q;
     57         initu();
     58         memset(gen,0,sizeof gen);      
     59         memset(cnt,0,sizeof cnt);      
     60         memset(dp,0,sizeof dp);        
     61         memset(cntgen,0,sizeof cntgen);
     62         kitogen.clear();
     63         REP(i,0,a) {
     64             int x,y;
     65             char s[4];
     66             scanf("%d%d%s", &x, &y, s);
     67             bool d = s[0]=='n';
     68             int a=findu(x), b=findu(y);
     69             if(a!=b) {
     70                 fa[a]=b;
     71                 fav[a]=fav[x]^fav[y]^d;
     72             }
     73         }
     74         if(p==q) {
     75             printf("no
    ");
     76             continue;
     77         } else {
     78             dp[0][0]=1;
     79             int ki = 0;
     80             REPE(i,1,n) {
     81                 int t = findu(i);
     82                 if(!gen[t]){ki++;gen[t]=true;cntgen[ki]=t;kitogen[t]=ki;}
     83                 cnt[kitogen[t]][fav[i]]++;
     84             }
     85 //            #define DBG(x,...) printf(x, ##__VA_ARGS__)
     86 //            REPE(i,1,ki) {
     87 //                DBG("%d: %d, %d @%d
    ", i, cnt[i][0], cnt[i][1], cntgen[i]);
     88 //            }
     89             REPE(i,1,ki){
     90                 for(int j=p;j>=0;j--){
     91                     if(j-cnt[i][0]>=0){
     92                         dp[i][j]+=dp[i-1][j-cnt[i][0]];
     93                     }
     94                     if(j-cnt[i][1]>=0){
     95                         dp[i][j]+=dp[i-1][j-cnt[i][1]];
     96                     }
     97                 }
     98             }
     99             if(dp[ki][p]!=1) {
    100                 printf("no
    ");
    101                 continue;
    102             } else {
    103                 int ansarr[MAXN], ansarri = 0; memset(ansarr,0,sizeof ansarr);
    104                 for(int i=ki;i>=1;i--) {
    105                     if(p-cnt[i][0]>=0&&dp[i-1][p-cnt[i][0]]){
    106                         for(int j=1;j<=n;j++){
    107                             if(fa[j]==cntgen[i]&&fav[j]==0)ansarr[ansarri++]=j;
    108                         }
    109                         p-=cnt[i][0];
    110                     } else if(p-cnt[i][1]>=0&&dp[i-1][p-cnt[i][1]]){
    111                         for(int j=1;j<=n;j++){
    112                             if(fa[j]==cntgen[i]&&fav[j]==1)ansarr[ansarri++]=j;
    113                         }
    114                         p-=cnt[i][1];
    115                     }
    116                 }
    117                 sort(ansarr,ansarr+ansarri);
    118                 REP(i,0,ansarri) {
    119                     printf("%d
    ", ansarr[i]);
    120                 }
    121                 printf("end
    ");
    122             }
    123         }
    124     }
    125     return 0;
    126 }
    AC代码
  • 相关阅读:
    sql2005 如何重启数据库服务
    jQuery 树控件 zTree
    谈C#中的Delegate
    微博首席架构师杨卫华:新浪微博技术架构分析(转)
    jqGrid 各种参数 详解
    asp.net(c#)ref,out ,params的区别
    gcc
    数据结构递归
    跳表
    javajvm
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10356873.html
Copyright © 2011-2022 走看看