codevs 1002 搭桥

Posted on 2015-12-13 16:43  ziliuziliu  阅读(197)  评论(0编辑  收藏  举报

codevs上的某一道最小生成树。我的方法可能较麻烦。。。先dfs找建筑物,再kruskal。这里并查集的使用是个关键。

这什么鬼的代码长度。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxe 100005
#define maxv 10005
using namespace std;
struct edge
{
int u,v,w;
}e[maxe];
struct building
{
int a,b;
}regis[maxv];
int n,m,map[55][55],vis[55][55],cnt=0,cntt=0,nume=0,father[5005];
int dx[]={0,0,1,1,1,0,-1,-1,-1},dy[]={0,-1,-1,0,1,1,1,0,-1};\
int num=0,sum=0;
char s[55];
bool judge(int x,int y)
{
if ((x>=1) && (x<=n) && (y>=1) && (y<=m) && (map[x][y]==1))
return true;
return false;
}
bool cmp(edge x,edge y)
{
return x.w<y.w;
}
void dfs(int x,int y,int fath)
{
vis[x][y]=1;regis[++cntt].a=x;regis[cntt].b=y;
father[(x-1)*m+y]=fath;
for (int i=1;i<=8;i++)
{
if ((judge(x+dx[i],y+dy[i])==true) && (vis[x+dx[i]][y+dy[i]]==0))
dfs(x+dx[i],y+dy[i],fath);
}
}
void addedge(int uu,int vv,int ww)
{
e[++nume].u=uu;
e[nume].v=vv;
e[nume].w=ww;
}
void build()
{
for (int i=1;i<=cntt;i++)
{
int kx=regis[i].a,ky=regis[i].b;
int up=max(1,regis[i].a-1),down=min(n,regis[i].a+1);
for (int j=up;j<=down;j++)
{
for (int k=1;k<=m;k++)
{
if (map[j][k]==1)
addedge((kx-1)*m+ky,(j-1)*m+k,abs(ky-k)-1);
}
}
int left=max(1,regis[i].b-1),right=min(m,regis[i].b+1);
for (int j=left;j<=right;j++)
{
for (int k=1;k<=n;k++)
{
if (map[k][j]==1)
addedge((kx-1)*m+ky,(k-1)*m+j,abs(kx-k)-1);
}
}
}
}
int getfather(int x)
{
if (x!=father[x])
father[x]=getfather(father[x]);
return father[x];
}
void unionn(int x,int y)
{
x=getfather(x);
y=getfather(y);
if (x!=y)
father[x]=y;
}
bool same(int x,int y)
{
if (getfather(x)==getfather(y))
return true;
return false;
}
void kruskal()
{
for (int i=1;i<=nume;i++)
{
if (same(e[i].u,e[i].v)==false)
{
unionn(e[i].u,e[i].v);
num++;
sum=sum+e[i].w;
}
}
}
int main()
{
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",s);
for (int j=0;j<m;j++)
if (s[j]=='#') map[i][j+1]=1;
}
for (int i=1;i<=n*m;i++)
father[i]=i;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
if ((vis[i][j]==0) && (map[i][j]==1))
{
vis[i][j]=1;
dfs(i,j,(i-1)*m+j);
cnt++;
}
}
printf("%d\n",cnt);
build();
sort(e+1,e+nume+1,cmp);
kruskal();
printf("%d %d",num,sum);
return 0;
}