zoukankan      html  css  js  c++  java
  • codevs1002搭桥(建图+Prim)

    /*
    先来个灌水法 然后建图跑最小生成树
    注意观察题目中的规则 a[1][i]!=a[1][j]&&abs(a[2][i]-a[2][j])<=1
    建图的时候可以每一个建筑物都看成一个点 然后计算需要几个桥
     同一个城市的不用桥 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    int n,m,tot,g[1001][1001],a[3][1001],minn[10001],f[10001],sum,bb;
    char s[101][101];
    int xx[9]={0,0,0,1,1,1,-1,-1,-1};//枚举8个方向 
    int yy[9]={0,1,-1,-1,0,1,-1,0,1};
    void Dfs(int x,int y)
    {
        s[x][y]=tot+48;
        int i,j,ox,oy;
        for(i=1;i<=8;i++)//枚举8个方向 
        {
          ox=x+xx[i];oy=y+yy[i];
          if(ox>0&&ox<=n&&oy>0&&oy<=m&&s[ox][oy]=='#')
            Dfs(ox,oy);
        }
    }
    int main()
    {
        cin>>n>>m;
        int i,j,k,l;
        for(i=1;i<=n;i++)
          for(j=1;j<=m;j++)
            cin>>s[i][j];
        for(i=1;i<=n;i++)
          for(j=1;j<=m;j++)
            if(s[i][j]=='#')//统计城市个数 
              {
                tot++;
                  Dfs(i,j);
              }
        cout<<tot<<endl;
        memset(g,1,sizeof(g));
        tot=0;//建筑物数量 
        for(i=1;i<=n;i++)
          {
              for(j=1;j<=m;j++)
                if(s[i][j]!='.')//记录每个建筑物的信息 
                  {
                    tot++;
                    a[1][tot]=i;//横坐标 
                    a[2][tot]=j;//纵坐标 
                }
          }
        for(i=1;i<=tot;i++)//建图(每个点都建 属于一个城市的不同桥) 
          for(j=i+1;j<=tot;j++)
            {
              if(a[1][i]!=a[1][j]&&abs(a[2][i]-a[2][j])<=1)//如果符合连桥的条件 
                {
                  g[i][j]=abs(a[1][i]-a[1][j])-1;
                  g[j][i]=g[i][j];
                }
              else if(a[2][i]!=a[2][j]&&abs(a[1][i]-a[1][j])<=1)
                {
                  g[i][j]=abs(a[2][i]-a[2][j])-1;
                  g[j][i]=g[i][j];
                }
            }
        memset(minn,1,sizeof(minn));
        minn[1]=0;
        for(i=1;i<=tot;i++)//跑 Prim 
          {
              k=0;
              for(j=1;j<=tot;j++)
                if(f[j]==0&&minn[j]<minn[k])
                  k=j;
              f[k]=1;
              for(j=1;j<=tot;j++)
                if(f[j]==0&&minn[j]>g[k][j])
                  minn[j]=g[k][j];
          }
        for(i=1;i<=tot;i++)
          {
              if(minn[i]!=0&&minn[i]<1000000)
              {
                  bb++;//统计桥的个数 
                  sum=sum+minn[i];//累加桥的长度 
              }
          }
        cout<<endl<<bb<<" "<<sum;
        return 0;
    }
  • 相关阅读:
    考研岁月
    sklearn 翻译笔记:KNeighborsClassifier
    网站不让复制的办法
    关于VMware Workstation 15 Player 虚拟机安装Windows系统却无法安装vmware tools的解决
    今天真是太傻了
    GoogleHacking相关技巧
    判断ARP欺骗
    Linux各个文件及其含义
    小白的开始—转一篇Linux系统入门的文章
    课时39.细线表格(理解)
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5424182.html
Copyright © 2011-2022 走看看