ACM数据结构专题

ACM数据结构专题

  • A题
    • 思路
    • 代码&解释
    • 总结
  • B题
    • 思路
    • 代码&解释
    • 总结

A题

思路

其实是一道括号匹配题,可以使用数据结构的

  • 如果是’(’,入栈。
  • 如果是’)’,栈非空则出栈。栈空则累加多余括号。
  • 最后加上栈中剩余元素和。

代码&解释

int t,n,i;
int main()
{
    scanf("%d",&t);
    while(t--){
    	int z=0,cnt=0;//z表示虚拟栈中元素,cnt累加多余的')'
    	scanf("%d",&n);
    	char c[n];
    	getchar();
    	scanf("%s",c);
    	for(i=0;i<n;i++){
    		if(c[i]=='(')z++;//左括号进栈
    		else if(z>0)z--;//栈非空出栈
    		else cnt++;//累加多余')'
    	}
    	printf("%d\n",cnt+z);
    }
    return 0;
}

总结

  • 有时候可以模拟栈不需要用真正的栈,虽然代码可读性下降了但节约了栈操作的时间。
  • 不要用gets! 用scanf("%s")读入无空格字符串。

B题

思路

这题相当于统计构成路的条数,这里提示了使用并查集

  • 罐子中钥匙存储形成的路必以成环结束,有两种可能:一是自身把钥匙放在自己里面虽然不知道怎么做到的,二是和其他罐子围成环。
  • 每个结点找他们的各自的爹的暂时终极爹,找到了过后让他做自己的爹,我愿称之为你和你爹平起平坐压缩路径不然每次都要重复走会tle的。
  • 一开始令自己的终极爹是自己,表示自己还未被访问。
    代码里的终极爹是成环后血缘链的顶端

代码&解释

int n,b[1000001],f[1000001],i,cnt;//b是暂时爸爸,f是终极爹
int find_f(int x){
    if(f[x]==x)return x;//第一次访问或自己是自己的爹
    return f[x]=find_f(f[x]);//爹有别的爹,找爹并且认爹
}
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&b[i]);//暂时爸爸
        f[i]=i;//开局自己是自己的暂时终极爹
    }
    for(i=1;i<=n;i++){
        if(find_f(b[i])==i){//爹的终极爹是自己
            cnt++;//构成一条血缘链
        }else f[i]=b[i];//没有找到终极爹,让暂时爸爸做暂时终极爹
    }
    printf("%d\n",cnt);
    return 0;
}

总结

  • 判断找爸爸的结束情况,让并查集能够结束递归。
  • 每次找完爸爸都要压缩路径,不然重复的递归浪费时间。

你可能感兴趣的:(算法)