UVALive 6525 Attacking rooks

将行中连续的‘ . ‘当作X集的一个点,列中连续的’ . ‘看成Y集中的一个点,然后把每一个’ . ‘看成一条边,连接Xi,Yj。

则问题转化成求此二分的最大匹配数。每找到一条匹配边的意义是找到了一个点放置一个,并且覆盖了所在的连续的行和列。

所以答案即为此二分图的最大匹配。

20s的时限,只跑了29ms。。。。这是有多不相信自己的服务器。。。。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long LL
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007
#define LM(a,b) (((ULL)(a))<<(b))
#define RM(a,b) (((ULL)(a))>>(b))

using namespace std;

const LL MAXN = 100001;

struct N
{
    int v,next;
}edge[MAXN*2];

int head[MAXN];

int Top;

void Link(int u,int v)
{
    edge[Top].v = v;

    edge[Top].next = head[u];
    head[u] = Top++;
}

void Init_head_Top(int n)
{
    memset(head,-1,sizeof(int)*(n+2));
    Top = 0;
}

int Match_Point[MAXN];

bool mark[MAXN];

bool dfs(int s)
{
    for(int p = head[s] ; p != -1; p = edge[p].next)
    {
        if(mark[edge[p].v] == false)
        {
            mark[edge[p].v] = true;
            if(Match_Point[edge[p].v] == -1 || dfs(Match_Point[edge[p].v]))
            {
                Match_Point[s] = edge[p].v;
                Match_Point[edge[p].v] = s;
                return true;
            }
        }
    }
    return false;
}

int Cal_Max_Match(int n)
{
    int ans = 0;

    for(int i = 1;i <= n; ++i)
    {
        if(Match_Point[i] == -1)
        {
            memset(mark,false,sizeof(bool)*(n+2));
            if(dfs(i))
                ans++;
        }
    }
    return ans;
}

char Map[110][110];

int ansx[110][110];
int ansy[110][110];

int main()
{
    int n;

    int i,j;

    while(scanf("%d",&n) != EOF)
    {
        for(i = 1;i <= n; ++i)
        {
            scanf("%s",Map[i]+1);
        }

        memset(ansx,-1,sizeof(ansx));
        memset(ansy,-1,sizeof(ansy));
        memset(Match_Point,-1,sizeof(int)*(n*n*2+2));

        int ty = 0;

        for(i = 1;i <= n; ++i)
        {
            for(j = 1;j <= n; ++j)
            {
                if(Map[i][j] == ‘.‘)
                {
                    ansx[i][j] = (ansx[i][j-1] == -1 ? ++ty : ansx[i][j-1]);
                }
            }
        }

        Init_head_Top(n*n*2);

        int ans = 0;

        for(j = 1;j <= n; ++j)
        {
            for(i = 1;i <= n; ++i)
            {
                if(Map[i][j] == ‘.‘)
                {
                    ansy[i][j] = (ansy[i-1][j] == -1 ? ++ty : ansy[i-1][j]);
                    Link(ansx[i][j],ansy[i][j]);
                    Link(ansy[i][j],ansx[i][j]);
                    if(Match_Point[ansx[i][j]] == -1 && Match_Point[ansy[i][j]] == -1)
                    {
                        Match_Point[ansx[i][j]] = ansy[i][j],Match_Point[ansy[i][j]] = ansx[i][j],ans++;
                    }
                }
            }
        }

        printf("%d\n",ans+Cal_Max_Match(ty));

    }
    return 0;
}

UVALive 6525 Attacking rooks

时间: 2024-08-27 03:03:45

UVALive 6525 Attacking rooks的相关文章

UVALive 6525 Attacking rooks(二分图最大匹配)

Attacking rooks 在一个n*n的图中,'X'代表卒,在'.'的地方放置尽量多的车,使得它们不互相攻击.问最多可放置车的数目. 和Fire Net一样,但这里图是100*100的,搜索会超时(其实我还脑残的试了试). 正解是二分图匹配,将每行中连续为.的作为X集合中一个点,同样,将每列中连续为.的点作为Y集合中的一个点.对原图中每个'.',将其对应的X集合和Y集合中的标号建边,便形成了二分图,对该图求最大匹配,每形成一个匹配即选择该点放车,那么与它相同编号的行和列都被覆盖了,都不能被

UVALive 6525 Attacking rooks 二分匹配 经典题

题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=4536">点击打开链接 题意: 给定n*n的棋盘, 能够在'.'上摆 象棋中的车(X是墙壁) 使得随意两个车都不能互相攻击到 问:最多能摆多少个车. 思路: 二分匹配 1.若没有X.那么做法就是 X点集为行,Y点集为列,对于图上的每一个点所在的行和列(x,y) 建一条边 x->y 2.有了X,那么对于每一个点所在的上方能接触到的X必须

LA 6525 Attacking rooks 二分匹配

题意: 给定n*n的棋盘, 可以在'.'上摆 象棋中的车(X是墙壁) 使得任意两个车都不能互相攻击到 求最多能摆多少个车. 思路:将每行中连续为.的作为X集合中一个点,同样,将每列中连续为.的点作为Y集合中的一个点.对原图中每个'.',将其对应的X 集合和Y集合中的标号建边,便形成了二分图,对该图求最大匹配.详见代码: /********************************************************* file name: LA6525.cpp author :

Hoj 13028 Attacking rooks

http://acm.hnu.cn/online/?action=problem&type=show&id=13028&courseid=0 题意:国际象棋里rooks里的规则(跟象棋没什么区别吧……).在N*N的棋盘里放置几个'X',如果两个rook之间有'X'就不会互相攻击,问棋盘里最多能放置几个rook. 题解:标准的二分图匹配.行列之间建边.根据'X'建立新行和新列. 1 #include <climits> 2 #include <cstdio>

HNU13028Attacking rooks (二分匹配,一行变多行,一列变多列)

Attacking rooks Time Limit: 20000ms, Special Time Limit:50000ms, Memory Limit:65536KB Total submit users: 12, Accepted users: 7 Problem 13028 : No special judgement Problem description Chess inspired problems are a common source of exercises in algor

1005 - Rooks(规律)

1005 - Rooks   PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move vertically or horizontally from its current positio

Lightoj 1005 Rooks(DP)

A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move vertically or horizontally from its current position and two rooks attack each other if one is on the path of the other. In the following fig

(light OJ 1005) Rooks dp

http://www.lightoj.com/volume_showproblem.php?problem=1005    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move vert

SGU[222] Little Rooks

Description 描述 Inspired by a "Little Bishops" problem, Petya now wants to solve problem for rooks. A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move horizontally and vertically from its