zoukankan      html  css  js  c++  java
  • P4304 [TJOI2013]攻击装置

    题意描述:

    给你一个(0,1) 矩阵,可以在 (0) 位置放攻击装置,每个位置可以攻击到一些地方。

    问你最多可以放多少个攻击装置使得这几个攻击装置互不攻击。

    solution:

    我们对于这个位置以及这个位置可以攻击到的位置连边。

    问题就转化为了求二分图的最大独立集。

    二分图的最大独立集等于总点数减去最大匹配数。

    匈牙利算法或者网络流求解即可。

    如果使用匈牙利算法求解的话,注意一开始要 (dfs) 一遍,找到左侧的边。

    成功的跑到了泥古 (rk2) .

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 40000;
    int n,cnt,ans,top,tot;
    int head[N],sta[N],match[N],col[N],id[510][510];
    bool vis[N],used[N];
    char s[510][510];
    int dx[8] = {-1,-2,1,2,-1,-2,1,2};
    int dy[8] = {-2,-1,-2,-1,2,1,2,1};
    struct node
    {
    	int to,net;
    }e[2000010];
    void add(int x,int y)
    {
    	e[++tot].to = y;
    	e[tot].net = head[x];
    	head[x] = tot;
    }
    void DFS(int x,int c)//二分图染色,把左侧的点找出来
    {
    	col[x] = c; vis[x] = 1;
        if(c == 1) sta[++top] = x;
        for(int i = head[x]; i; i = e[i].net)
        {
            int to = e[i].to;
            if(!col[to]) DFS(to,3-c);
        }
    }
    bool dfs(int x)
    {
        for(int i = head[x]; i; i = e[i].net)
        {
            int to = e[i].to;
            if(!used[to])
            {
                used[to] = 1;
                if(!match[to] || dfs(match[to]))
                {
                    match[to] = x;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) scanf("%s",s[i]+1);
        for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(s[i][j] == '0') id[i][j] = ++cnt;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(s[i][j] == '1') continue;
                for(int k = 0; k < 8; k++)
                {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(x < 1 || x > n || y < 1 || y > n) continue;
                    if(s[x][y] == '0') add(id[i][j],id[x][y]);
                }
            }
        } 
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(s[i][j] == '0' && !col[id[i][j]]) DFS(id[i][j],1); 
            }
        }
        for(int i = 1; i <= top; i++)
        {
            memset(used,0,sizeof(used));
            if(dfs(sta[i])) ans++;
        }
        printf("%d
    ",cnt-ans);
        return 0;
    }
    
  • 相关阅读:
    深度优先和广度优先
    水管工游戏(深度优先)
    炸弹人
    广度优先(迷宫找人)
    System.Data.Entity.Core.MetadataException: 无法加载指定的无数据资源
    Element Cascader 级联选择器 单选操作优化
    Windows服务 ProjectInstaller 获取 路径
    Quartz.NET ScheduledFireTimeUtc 当超过1分钟时出现的问题。
    记录:一个SQL SERVER奇怪的问题。
    log4.net 配置
  • 原文地址:https://www.cnblogs.com/genshy/p/14350592.html
Copyright © 2011-2022 走看看