zoukankan      html  css  js  c++  java
  • NOIP模拟 water 最小生成树

    题面不给……题意:求出一个高低不平的矩阵每个点可盛水的多少,注意边框高度为$0$。

    本来以为是个$bfs$……结果一个多小时没调出来……

    结果被正解吓傻了……竟然是个最小生成树……我们可以发现每个点水位最高值可以看做从边界到达这个点路上经过的最高点的最小值……然后我们就上下左右连边……边权就是两点之中较高那个点的海拔……特别的边界上的边权为$max(权值,0)$。

    然后就是个最小生成树=   =……然后以外边框映射出的点$dfs$动态求出边权最大值即可=  =……

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 const int maxn=305;
     7 int map[maxn][maxn],n,m,id[maxn][maxn],dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
     8 struct node
     9 {
    10     int from,to,val,next;
    11     bool operator <(const node &b)const
    12     {
    13         return val<b.val;
    14     }
    15 }edge[maxn*maxn*20];
    16 int head[maxn*maxn],tot,cnt;
    17 void addedge(int u,int v,int w)
    18 {
    19     edge[++tot]=(node){u,v,w,head[u]};head[u]=tot;
    20 }
    21 int fa[maxn*maxn];
    22 int getfa(int x)
    23 {
    24     return fa[x]==x?x:fa[x]=getfa(fa[x]);
    25 }
    26 void unionn(int x,int y)
    27 {
    28     x=getfa(x),y=getfa(y);
    29     if(x!=y)fa[y]=x;
    30 }
    31 void Kruskal()
    32 {
    33     memset(head,0,sizeof(head));int num=0;sort(edge+1,edge+tot+1);
    34     for(int i=1;i<=tot;i++)
    35     {
    36         int u=edge[i].from,v=edge[i].to;
    37         if(getfa(u)!=getfa(v))
    38         {
    39             unionn(u,v);addedge(u,v,edge[i].val),addedge(v,u,edge[i].val);num++;
    40             if(num==cnt)break;
    41         }
    42     }
    43 }
    44 int dis[maxn*maxn],pa[maxn*maxn];
    45 void dfs(int now,int fat)
    46 {
    47     pa[now]=fat;
    48     for(int i=head[now];i;i=edge[i].next)
    49     {
    50         int v=edge[i].to;
    51         if(v!=fat){dis[v]=max(dis[now],edge[i].val);dfs(v,now);}
    52     }
    53 }
    54 int haha()
    55 {
    56     scanf("%d%d",&n,&m);
    57     for(int i=1;i<=n;i++)
    58         for(int j=1;j<=m;j++)id[i][j]=++cnt,scanf("%d",&map[i][j]);
    59     for(int i=1;i<=n;i++)
    60         for(int j=1;j<=m;j++)
    61             for(int d=0;d<4;d++)
    62             {
    63                 int x=i+dx[d],y=j+dy[d];
    64                 if(x==0||x==n+1||y==0||y==n+1)addedge(0,id[i][j],max(map[i][j],0)),addedge(id[i][j],0,max(map[i][j],0));
    65                 else addedge(id[i][j],id[x][y],max(map[i][j],map[x][y]));
    66             }
    67     for(int i=0;i<=cnt;i++)fa[i]=i;
    68     Kruskal();dis[0]=(int)-1e9-1;dfs(0,-1);
    69     for(int i=1;i<=n;i++)
    70     {
    71         for(int j=1;j<=m;j++)printf("%d ",dis[id[i][j]]-map[i][j]);
    72         puts("");
    73     }
    74 }
    75 int sb=haha();
    76 int main(){;}
    77 
    78 B
    B
  • 相关阅读:
    Markdown编辑器语法指南2
    python文件读写的学习
    K:图相关的最小生成树(MST)
    K:哈弗曼树
    K:树、二叉树与森林之间的转换及其相关代码实现
    K:二叉树
    K:树与二叉树
    KandQ:那年,那树,那些知识点
    K:java中的安全模型(沙箱机制)
    K:java中的RMI(Remote Method Invocation)
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7624551.html
Copyright © 2011-2022 走看看