• [国家集训队] 部落战争


    18.10.04模拟赛T2。

    毒瘤出题人zzk祭出二分图匹配,然而zwz还是A了......

    事实证明zwz大佬是卡不住的。

    洛谷 P2172 传送门

    首先如果每个点都放一个军队的话,总数就是城镇的个数。

    但是这样的话就会很浪费。

    从上到下,所有可转移的点之间连边,但是这道题要求每个点只能走一次,怎么办呢?

    每个点只能走一次,每个人只能有一个对象,这不就是二分图吗(原谅我对二分图的猥琐见解)。

    接下来就让那些点乱搞对象匹配(原谅我对匈牙利算法的猥琐见解)(原谅我的变量名cp)。

    每有一个匹配,就节省一支军队。

    最后就用总数减去匹配数就好了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int m,n,r,c;
     7 int d[55][55];
     8 int cp[2505],vis[2505];
     9 int dx[10],dy[10];
    10 int hd[2505],to[10005],nx[10005],ec;
    11 int tot,ans;
    12 
    13 int id(int x,int y)
    14 {
    15     return n*(x-1)+y;
    16 }
    17 
    18 void edge(int af,int at)
    19 {
    20     to[++ec]=at;
    21     nx[ec]=hd[af];
    22     hd[af]=ec;
    23 }
    24 
    25 void add(int x,int y)
    26 {
    27     for(int i=1;i<=4;i++)
    28     {
    29         int tx=x+dx[i],ty=y+dy[i];
    30         if(tx<=0||tx>m||ty<=0||ty>n)continue;
    31         if(!d[tx][ty])
    32             edge(id(tx,ty),id(x,y));
    33     }
    34 }
    35 
    36 int ex(int p)
    37 {
    38     for(int i=hd[p];i;i=nx[i])
    39     {
    40         int des=to[i];
    41         if(vis[des]!=tot)
    42         {
    43             vis[des]=tot;
    44             if(!cp[des]||ex(cp[des]))
    45             {
    46                 cp[des]=p;
    47                 return 1;
    48             }
    49         }
    50     }
    51     return 0;
    52 }
    53 
    54 void hungary()
    55 {
    56     for(int i=1;i<=m;i++)
    57     {
    58         for(int j=1;j<=n;j++)
    59         {
    60             if(d[i][j])continue;
    61             tot++;
    62             if(ex(id(i,j)))ans++;
    63         }
    64     }
    65 }
    66 
    67 int main()
    68 {
    69     scanf("%d%d%d%d",&m,&n,&r,&c);
    70     dx[1]=dx[2]=-c,dx[3]=dx[4]=-r;
    71     dy[1]=r,dy[2]=-r,dy[3]=c,dy[4]=-c;
    72     for(int i=1;i<=m;i++)
    73     {
    74         char tmp[55];
    75         scanf("%s",tmp+1);
    76         for(int j=1;j<=n;j++)
    77         {
    78             if(tmp[j]=='x')d[i][j]=1;
    79             else add(i,j);
    80         }
    81     }
    82     hungary();
    83     printf("%d
    ",tot-ans);
    84     return 0;
    85 }
  • 相关阅读:
    PHP exif扩展方法开启详解(亲测)
    t470安装win7
    (转)如何在Excel2013中制作条形码
    office文件密码破解方法及软件
    解决 this virtual machine’s policies are too old to be run by this version of vmware workstation”
    xp系统下网络打印机怎么设置
    (转载)Excel文档保存的时候,提示“文档未保存”
    java环境变量配置
    转载 __builtin_expect — 分支预测优化
    分布式系统知识点十五:到底servermesh是咋样的,解决啥问题(转载)
  • 原文地址:https://www.cnblogs.com/cervusy/p/9744169.html
Copyright © 2020-2023  润新知