zoukankan      html  css  js  c++  java
  • EZOJ 宝石迷阵 建图+网络流匹配

    题面:

      封印恶魔的地方可以看作是一个 n*m 的矩形,包含了 n*m 个祭坛,并且其 中有一些祭坛已经损坏了。

      如果 i+j 为偶数,那么第 i 行第 j 列的祭坛只要没有损坏,就一定会封印有一个恶魔。

       其他的没有损坏的祭坛可以用来放置魔法水晶,但是一个祭坛上只能放置一 个魔法水晶,并且一个魔法水晶只能向一个与它相邻的祭坛输送魔力,从而加固 封印。

       对于一个恶魔来说,如果与它相邻的两个成直角的水晶同时向它所在的祭坛 输送魔力的话,它就会被再次封印。 现在 Z 君想知道他最多可以封印多少恶魔?

    分析:

      这道题一眼看上去比较乱,但是其中的关系却很简单。

      若格子没有损坏,i+j为偶数则为恶魔,否则为魔法水晶,两个魔法水晶与一个恶魔相邻且成直角,就可以选择一起封印他。

      我们仔细一想:什么叫成直角!?!?说的那么文艺,实际上就是与同一个恶魔相邻的位于奇数列和偶数列的两个魔法水晶!

      那不就好办了?我们将奇数列和偶数列的魔法水晶分开来考虑,将恶魔拆成两个点,就形成了“一个人喜欢两类物品中的各一种,只能各选一种,问最多几人满意”这样的问题,于是就和我们上一篇中讨论的问题一样的了,拆点、连边、最大流、结束!

    代码:(我不知道为啥别人都写了一百大几十行……)

     1 #include<bits/stdc++.h>
     2 #define ms(a,x) memset(a,x,sizeof(a))
     3 using namespace std;int tot=0;
     4 const int N=10005,inf=0x3f3f3f3f;
     5 int S,T,q[N],h[N],c=1,n,m,k,d[N],cnt=0;
     6 int c1[55][55][2],fx[4]={1,0,-1,0};
     7 struct node{int y,z,nxt;}e[N*2];
     8 int fy[4]={0,1,0,-1};char s[55];
     9 bool isb(int i,int j){
    10     return c1[i][j][0]!=0;
    11 } bool isn(int i,int j){
    12     return ((i+j)&1);
    13 } void add(int x,int y,int z){
    14     e[++c]=(node){y,z,h[x]};h[x]=c;
    15     e[++c]=(node){x,0,h[y]};h[y]=c;
    16 } bool bfs(){
    17     int f=1,t=0;ms(d,-1);
    18     q[++t]=S;d[S]=0;
    19     while(f<=t){
    20         int x=q[f++];
    21         for(int i=h[x],y;i;i=e[i].nxt)
    22         if(d[y=e[i].y]==-1&&e[i].z)
    23         d[y]=d[x]+1,q[++t]=y;
    24     } return (d[T]!=-1);
    25 } int dfs(int x,int f){
    26     if(x==T) return f;int w,tmp=0;
    27     for(int i=h[x],y;i;i=e[i].nxt)
    28     if(d[y=e[i].y]==d[x]+1&&e[i].z){
    29         w=dfs(y,min(e[i].z,f-tmp));
    30         if(!w) d[y]=-1;
    31         e[i].z-=w;e[i^1].z+=w;
    32         tmp+=w;if(tmp==f) return f;
    33     } return tmp;
    34 } void dinic(){
    35     while(bfs()) tot+=dfs(S,inf);
    36 } int main(){
    37     scanf("%d%d",&n,&m);S=0;
    38     for(int i=1;i<=n;i++){
    39         scanf("%s",s+1);
    40         for(int j=1;j<=m;j++){
    41             if(s[j]=='X') continue;
    42             c1[i][j][0]=++cnt;
    43             if(!isn(i,j)) c1[i][j][1]=++cnt,
    44             add(c1[i][j][0],c1[i][j][1],1);
    45         }
    46     } T=++cnt;
    47     for(int i=1;i<=n;i++)
    48     for(int j=1;j<=m;j++){
    49         if(!isb(i,j)) continue;
    50         if(isn(i,j))
    51         for(int v=0;v<4;v++){
    52             int x=i+fx[v],y=j+fy[v];
    53             if(!isb(x,y)) continue;
    54             if(j&1) 
    55             add(c1[i][j][0],c1[x][y][0],1);
    56             else
    57             add(c1[x][y][1],c1[i][j][0],1);
    58         } if(isn(i,j)){
    59             if(j&1) add(S,c1[i][j][0],1);
    60             else add(c1[i][j][0],T,1);
    61         }
    62     } dinic();
    63     printf("%d
    ",tot);
    64     return 0;
    65 }
    拆点最大流
  • 相关阅读:
    序列——堆排序-大根堆(堆大顶)
    3 分钟的高速体验 Apache Spark SQL
    UVa 1401 Remember the Word
    leetcode
    oracle看到用户的所有表名、表睐、字段名称、现场的目光、是空的、字段类型
    cocos2d-x物业现场
    Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket
    ThreadPoolExecutor详解
    Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
    A First Exploration Of SolrCloud
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10242465.html
Copyright © 2011-2022 走看看