• codevs 1002 搭桥


    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 ",cnt);
    build();
    sort(e+1,e+nume+1,cmp);
    kruskal();
    printf("%d %d",num,sum);
    return 0;
    }

  • 相关阅读:
    Linux makefile 教程 很具体,且易懂
    工作流技术学习
    23种设计模式(5):原型模式
    NETSH WINSOCK RESET这条命令的含义和作用?
    OpenGL中shader使用
    【我所認知的BIOS】—&gt;ADU.exe
    socket通信简单介绍
    Android开发之合并文件的几种方式
    Python 单词字母顺序不变且所有倒排
    VC2010 Working Directory
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5043044.html
Copyright © 2020-2023  润新知