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;
}
原文地址:https://www.cnblogs.com/genshy/p/14350592.html