• 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 }
    拆点最大流
  • 相关阅读:
    4.9cf自训9..
    数位dp-入门模板题 hdu2089
    熟能生巧 汽车停车入位技巧解析-倒车入库--侧边停车
    MyBatis参数传入集合之foreach动态sql
    jquery如何判断checkbox(复选框)是否被选中
    Mybatis关联查询(嵌套查询)
    Mysql 分页语句Limit用法
    $.ajax返回的JSON格式的数据后无法执行success的解决方法
    JavaWeb学习总结(十二)——Session
    Spring MVC中Session的正确用法之我见
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10242465.html
Copyright © 2020-2023  润新知