zoukankan      html  css  js  c++  java
  • 【hdu 4859】海岸线(图论--网络流最小割)

    题意:有一个区域,有'.'的陆地,'D'的深海域,'E'的浅海域。其中浅海域可以填充为陆地。这里的陆地区域不联通,并且整个地图都处在海洋之中。问填充一定浅海域之后所有岛屿的最长的海岸线之和。

    解法:最小割。从“分隔”陆地和海域可以想到“割”的概念,然后我们先不考虑浅海域,要深海域和陆地的对数尽量大,也就是相同的地理构造对数尽量小。
          于是我们建立一个二分图,深海域和陆地都分列两侧,对于相邻的一个在左,一个在右,也就是“行+列”是奇数的放左,偶数的在右。而对于相邻的深海域和陆地,它们在图中理应分列两侧,才有“相连”的意义。(唉,我算是“梗着脖子”地在解释......~(-仝-)~)于是可以深海域的奇数的在左,而陆地的偶数的在左。
          接着建立一个源点和汇点,左侧的点与源点相连,右侧的点与汇点相连。由于无约束,边容量为INF。而4个方向相邻的都“相连”,便建边,容量为1,表示割这条边的代价就是1。又因为这整个地图都处在海洋之中,也就是这个地图外围是一圈深海域,这是隐含条件,所以还需要另外建这些点和对应的边。
          最后,用最大流算法求出最小割,表示相同的地理构造的最少的对数,而最长的海岸线就是最多的不同的构造,也就是总对数-最少的相同的地理构造的对数。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<queue>
      6 using namespace std;
      7 
      8 const int N=50,NN=3000,MM=30000,INF=20000;
      9 int n,m,len=1;
     10 int last[NN],d[NN];
     11 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
     12 char s[N][N];
     13 struct node{int x,y,fl,next;}a[MM];
     14 queue<int> q;
     15 
     16 int mmin(int x,int y) {return x<y?x:y;}
     17 void ins(int x,int y,int fl)
     18 {
     19     a[++len].x=x,a[len].y=y,a[len].fl=fl;
     20     a[len].next=last[x],last[x]=len;
     21     a[++len].x=y,a[len].y=x,a[len].fl=0;
     22     a[len].next=last[y],last[y]=len;
     23 }
     24 bool bfs(int st,int ed)
     25 {
     26     while (!q.empty()) q.pop();
     27     memset(d,0,sizeof(d));
     28     q.push(st); d[st]=1;
     29     while (!q.empty())
     30     {
     31       int x=q.front(); q.pop();
     32       for (int i=last[x];i;i=a[i].next)
     33       {
     34         int y=a[i].y;
     35         if (!a[i].fl||d[y]) continue;
     36         d[y]=d[x]+1; q.push(y);
     37       }
     38     }
     39     return d[ed];
     40 }
     41 int dfs(int x,int flow,int ed)
     42 {
     43     if (x==ed) return flow;
     44     int sum=0;
     45     for (int i=last[x];i;i=a[i].next)
     46     {
     47       int y=a[i].y;
     48       if (d[y]!=d[x]+1||!a[i].fl) continue;
     49       int t=dfs(y,mmin(flow-sum,a[i].fl),ed);
     50       sum+=t;
     51       a[i].fl-=t,a[i^1].fl+=t;
     52       if (sum==flow) break;
     53     }
     54     if (!sum) d[x]=0;
     55     return sum;
     56 }
     57 int Max_flow(int st,int ed)
     58 {
     59     int sum=0;
     60     while (bfs(st,ed)) sum+=dfs(st,INF,ed);
     61     return sum;
     62 }
     63 int ID(int x,int y) {return (x-1)*m+y;}
     64 int main()
     65 {
     66     int T;
     67     scanf("%d",&T);
     68     for (int kase=1;kase<=T;kase++)
     69     {
     70       scanf("%d%d",&n,&m);
     71       for (int j=1;j<=m+2;j++) s[1][j]='D';
     72       for (int i=2;i<=n+1;i++)
     73       {
     74         scanf("%s",s[i]+2);
     75         s[i][1]=s[i][m+2]='D';
     76       }
     77       for (int j=1;j<=m+2;j++) s[n+2][j]='D';
     78       n+=2,m+=2;
     79       
     80       int st=n*m+1,ed=n*m+2;
     81       memset(last,0,sizeof(last));
     82       len=1;
     83       for (int i=1;i<=n;i++)
     84       {
     85         for (int j=1;j<=m;j++)
     86         {
     87           if (i==1||i==n||j==1||j==m) s[i][j]='D';
     88           int t=ID(i,j);
     89           if (s[i][j]=='.')
     90           {
     91             if ((i+j)%2) ins(st,t,INF);
     92             else ins(t,ed,INF);
     93           }
     94           if (s[i][j]=='D')
     95           {
     96             if ((i+j)%2) ins(t,ed,INF);
     97             else ins(st,t,INF);
     98           }
     99           for (int k=0;k<4;k++)
    100           {
    101             int x=i+dx[k],y=j+dy[k],tt=ID(x,y);
    102             if (x<1||y<1||x>n||y>m) continue;
    103             ins(t,tt,1);
    104           }
    105         }
    106       }
    107       int ans=Max_flow(st,ed);
    108       ans=(n-1)*m+(m-1)*n-ans;
    109       printf("Case %d: %d
    ",kase,ans);
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    研赛02939有理多项式的根的问题
    [真题解析]广州大学2010年高等代数05(01)正定矩阵的和的逆不等于逆的和
    [真题解析]广州大学2011年高等代数考研试题参考解答04(考得太多的)稍微做下初等列变换的循环矩阵的行列式
    [真题解析]广州大学2011年高等代数考研试题参考解答02跟着命题人思路走, 第2问定要用上第1问哦
    [真题解析]广州大学2012年高等代数考研试题参考解答03用反证法推理时定要有理有据!
    [真题解析]广州大学2011年高等代数考研试题参考解答09子空间和的正交补等于正交补的交
    先进计算产业发展 白皮书
    《审美教育书简》笔记
    《欢迎来到你的世界:建筑如何塑造我们的情感、认知和幸福》笔记
    《论美国的民主》笔记
  • 原文地址:https://www.cnblogs.com/konjak/p/6059703.html
Copyright © 2011-2022 走看看