自己画图半天才整明白
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
int main()
{
char q[100],h[100];
scanf("%s",q);scanf("%s",h);
int l=strlen(q);
int end=1;
for(int i=0;i<l-1;i++){
for(int j=1;j<l;j++){
if(q[i]==h[j]&&q[i+1]==h[j-1]){
end*=2;
}
}
}
printf("%d",end);
return 0;
}
//只需要寻找只有单个字节点的节点
//先序为父左右,后序为左右父
//如果夫只有一个字,则一定是父子:子父
//无论先序还是后序都不能将其分离
初版代码,直接题解有三个代码超时,开O2能过
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
int num[100010]={0};
int main()
{
int n,t;
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++) num[i]=i;
int tip,x,y;
for(int ok=0;ok<t;ok++){
// printf("%d\n",ok);
// printf("\nsr:");
scanf("%d%d%d",&tip,&x,&y);
// printf("\n");
if(tip==1){
int a=x,b=y;
while(a!=num[a])a=num[a];
while(b!=num[b])b=num[b];
num[b]=a;
}
else{
int a=x,b=y;
while(a!=num[a])a=num[a];
while(b!=num[b])b=num[b];
if(a==b) printf("Y\n");
else printf("N\n");
}
// printf("*%d\n",ok);
// for(int i=1;i<=n;i++) printf("%d ",num[i]);
// printf("\n");
}
return 0;
}
看了洛谷题解的递归方法,发现可以把多代关系都压成一代,31ms过了
如果a有上一代集合,用c标记num[a]的位置(这一代),a=num[a]去找上一代,而num[c](原来的num[a])改成num[a]相当于向上一代移动一个位置
把
while(a!=num[a])a=num[a];
替换为
while(a!=num[a]){
int c=a;a=num[a];num[c]=num[a];
}
b同理
稍微改一下就并查集模板就出来了(吃个饭就忘记模板了,想半天才ac)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
int num[100010]={0};
int main()
{
int n,m,p;
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++) num[i]=i;
int a,b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
int x=a,y=b;
while(x!=num[x]){
int c=x;x=num[x];num[c]=num[x];
}
while(y!=num[y]){
int c=y;y=num[y];num[c]=num[y];
}
num[y]=x;
}
for(int i=0;i<p;i++){
scanf("%d%d",&a,&b);
int x=a,y=b;
while(x!=num[x])x=num[x];
while(y!=num[y])y=num[y];
if(x==y) printf("Yes\n");
else printf("No\n");
}
return 0;
}
写这个题目的时候才注意到做前面两个并查集没有注意节点与上一代的大小关系,而这个题目开始强调相互间的大小关系
for(int i=0;i<p;i++){
scanf("%d%d",&x,&y);
a=x,b=y;
while(a!=man[a]){
c=a;a=man[a];man[c]=man[a];
}
while(b!=man[b]){
c=b;b=man[b];man[c]=man[b];
}
man[b]=man[a];
}
原来的代码段,假设输入1,2和 3,1
数组的值首先变为1,1,3
再变为 3,1,3
如果是要求所有节点最后的关联节点为1,就不符合题意了
(其实写的时候可以改成如果关联节点最后等于man[1]应该也可以)
加上比较两边各自的人数之后就过了
if(man[b]>man[a]) man[b]=man[a];
else man[a]=man[b];
ac代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
int man[20010]={0},wuman[20010]={0};
int main()
{
int n,m,p,q;
scanf("%d%d%d%d",&n,&m,&p,&q);
for(int i=0;i<=n;i++) man[i]=i;
for(int i=0;i<=m;i++) wuman[i]=i;
int a,b,c,x,y;
for(int i=0;i<p;i++){
scanf("%d%d",&x,&y);
a=x,b=y;
while(a!=man[a]){
c=a;a=man[a];man[c]=man[a];
}
while(b!=man[b]){
c=b;b=man[b];man[c]=man[b];
}
if(man[b]>man[a]) man[b]=man[a];
else man[a]=man[b];
}
for(int i=0;i<q;i++){
scanf("%d%d",&x,&y);
a=-x,b=-y;
while(a!=wuman[a]){
c=a;a=wuman[a];wuman[c]=wuman[a];
}
while(b!=wuman[b]){
c=b;b=wuman[b];wuman[c]=wuman[b];
}
if(wuman[b]>wuman[a]) wuman[b]=wuman[a];
else wuman[a]=wuman[b];
}
int op=1,ed=1;
for(int i=2;i<=n;i++){
a=i;
while(a!=man[a]) a=man[a];
if(a==1) op++;
}
for(int i=2;i<=m;i++){
a=i;
while(a!=wuman[a]) a=wuman[a];
if(a==1) ed++;
}
printf("%d",op<ed?op:ed);
return 0;
}