POJ 1417 True Liars
Posted sahdsg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1417 True Liars相关的知识,希望对你有一定的参考价值。
POJ连炸多日……
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 }
后来抄了个DP,还不知道怎么分析:(
还得多练DP:(
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 }
以上是关于POJ 1417 True Liars的主要内容,如果未能解决你的问题,请参考以下文章