您的位置:首页 > 其它

原来我可以这么的暴力,,,树,并查集,深搜~

2010-07-18 18:18 246 查看
1、http://acm.hdu.edu.cn/showproblem.php?pid=1198





解题思路:用深搜来标记从可行的一个位置出发所能达到的所有的点,组成一个连通的图块,求和~



#include<stdio.h>
#include<memory.h>
#define M 55
int dir[][2]={{0,1},{1,0},{0,-1},{-1,0}};
char judge[11][11][5]=
{//暴力倾注的查询表,不要问我为什么,不能解释...
	"0000","0010","0001","0011","0001","0010","0010","0001","0011","0011","0011",
	"1000","0000","1001","0001","0001","1000","1000","1001","1001","0001","1001",
	"0100","0110","0000","0010","0100","0010","0110","0100","0010","0110","0110",
	"1100","0100","1000","0000","0100","1000","1100","1100","1000","0100","1100",
	
	"0100","0100","0001","0001","0101","0000","0100","0101","0001","0101","0101",
	"1000","0010","1000","0010","0000","1010","1010","1000","1010","0010","1010",
	"1000","0010","1001","0011","0001","1010","1010","1001","1011","0011","1011",
	"0100","0110","0001","0011","0101","0010","0110","0101","0011","0111","0111",
	
	"1100","0110","1000","0010","0100","1010","1110","1100","1010","0110","1110",
	"1100","0100","1001","0001","0101","1000","1100","1101","1001","0101","1101",
	"1100","0110","1001","0011","0101","1010","1110","1101","1011","0111","1111"
};
char map[M][M];
int mark[M][M];
int r,c,count;
void dfs(int x,int y)
{
	int a,b,i;
	mark[x][y]=1;
	for(i=0;i<4;i++){
		a=x+dir[i][0];
		b=y+dir[i][1];
		if(!mark[a][b]&&a>=0&&a<r&&b>=0&&b<c
			&&(judge[map[x][y]-'A'][map[a][b]-'A'][i]=='1'))			
			dfs(a,b);
	}
}
void run()
{
	int i,j;
	for(i=0;i<r;i++){
		for(j=0;j<c;j++)
			if(!mark[i][j]){
				dfs(i,j);
				count++;
			}
	}
	return ;
}

int main()
{
	int i;
	while(scanf("%d%d",&r,&c),r!=-1&&c!=-1){
		for(i=0;i<r;i++)
			scanf("%s",map[i]);
		memset(mark,0,sizeof(mark));
		count=0;
		run();
		printf("%d/n",count);
	}
	return 0;
}






2、http://acm.hdu.edu.cn/showproblem.php?pid=1232



畅通工程,



解题思路:用并查集找出各连通分量,所需的最小路数即为其值减一;





/*使用并查集找出全部连通分量,即所生成的树个数*/
#include<stdio.h>
#include<memory.h>
#define M 1001
int father[M];
int n,m;
void init()
{//初始化
	int i;
	for(i=1;i<=n;i++)
		father[i]=i;
}

int root(int r)
{//查找元素r的根结点,压缩路径,
	if(!father[r])
		return father[r]=r;
	if(r!=father[r])
		father[r]=root(father[r]);
	return father[r];
}

void merge(int x,int y)
{//合并两集合
	int a,b;
	a=root(x);
	b=root(y);
	if(a!=b)
		father[b]=a;
}

int main()
{
	int i,a,b,sum;

	while(scanf("%d",&n),n){
		scanf("%d",&m);
		sum=0;init();
		while(m--){
			scanf("%d%d",&a,&b);
			father[a]=root(a);
			father[b]=root(b);
			merge(a,b);
		}
		for(i=1;i<=n;i++){//如果father[i]==i,则i为集合形成树的根结点
			if(father[i]==i)
				sum++;
		}
		printf("%d/n",sum-1);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: