CH6802车的放置(二分图最大匹配)

题    目    传    送    门    在    这



题目大意

题目都很简短了就不说了……(懒得打)

解题思路

我们把行和列都看作节点,对于每个可以放位置,连一条行到列的边。

我们发现这是一个二分图。

因为车不能互相攻击,对于第一行,只能放一个车,对于每一列也是如此,所以每个节点只有一条连边。

那么就符合二分图匹配中每两条边没有公共节点。

本题就变成求二分图最大匹配的题目。

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(x, l, r) for(int x = l; x <= r; x++)
#define repd(x, r, l) for(int x = r; x >= l; x--)
#define clr(x, y) memset(x, y, sizeof(x))
#define all(x) x.begin(), x.end()
#define pb push_back
#define mp make_pair
#define MAXN 105
#define MAXM 40005
#define fi first
#define se second
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int p = 10000007;
int lowbit(int x){ return x & -x; }
int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p; } return x; }

const int dic[4][2] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
int n, m, cnt;
int head[MAXN * MAXN], nxt[MAXM], to[MAXM];
int match[MAXN * MAXN];
bool g[MAXN][MAXN], vis[MAXN * MAXN];

void init(){
    cnt = 0;
    clr(head, -1);
    clr(match, 0);
}

int id(int x, int y){
    return (x - 1) * n + y;
}

void add(int u, int v){
    nxt[cnt] = head[u];
    head[u] = cnt;
    to[cnt] = v;
    cnt++;
}

bool dfs(int u){
    for(int e = head[u]; e != -1; e = nxt[e]){
        int v = to[e];
        if(vis[v]) continue;
        vis[v] = 1;
        if(!match[v] || dfs(match[v])){
            match[v] =  u;
            return 1;
        }
    }
    return 0;
}

int main(){
    init();
    scanf("%d%d", &n, &m);
    rep(i, 1, m){
        int x, y;
        scanf("%d%d", &x, &y);
        g[x][y] = 1;
    }
    rep(i, 1, n)
        rep(j, 1, n)
            if(!g[i][j])
                rep(k, 0, 3){
                    int x = i + dic[k][0], y = j + dic[k][1];
                    if(x > 0 && y > 0 && x <= n && y <= n && !g[x][y] && (x + y) % 2){
                        add(id(i, j), id(x, y));
                    }
                }
    int ans = 0;
    rep(i, 1, id(n, n)){
        clr(vis, 0);
        if(dfs(i)) ans++;
    }
    printf("%d\n", ans);
    return 0;
}

最后问一下,为什么mac自带输入法打不出“車”。

原文地址:https://www.cnblogs.com/SHANAchan/p/10343494.html

时间: 2024-11-13 06:59:36

CH6802车的放置(二分图最大匹配)的相关文章

HDU2063_过山车(二分图/最大匹配)

解题报告 题目传送门 题意: 求最大的男女匹配数目. 思路: 简单的最大匹配. #include <cstdio> #include <cstring> #include <iostream> using namespace std; int k,n,m,mmap[1100][1100],vis[550],pre[550]; int dfs(int x) { for(int i=1;i<=n;i++){ if(!vis[i]&&mmap[x][i]

[HDU] 2063 过山车(二分图最大匹配)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2063 女生为X集合,男生为Y集合,求二分图最大匹配数即可. 1 #include<cstdio> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<math.h> 6 #include<stdbool.h> 7 #include<ti

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

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

hdoj--1045&lt;dfs&amp;二分图最大匹配&gt;(这里是dfs解法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1045 题目描述: 在矩阵中放车,车可四面攻击,矩阵中有墙,可以防止攻击,给出墙的位置,输出最多可以放多少车: 题目要点:dfs&二分图最大匹配(匈牙利算法)(这里是dfs) 本题在一开始作的时候陷入了贪心的漩涡,写出来的以为是dfs.但实际上是谈心,而且贪心在这里是错误的:(贪心算法的应用范围比较窄,多数情况下是错误的) 然后发现了dfs与贪心的不同:贪心算法是每次放置车的方法都是固定,实际上并没有

图论——LCA、强联通分量、桥、割顶、二分图最大匹配、网络流

A: 交通运输线 时间限制: 5 Sec  内存限制: 128 MB 题目描述 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路.当然在运输线中,更不可能存在圈. 现在,你的任务来了.给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度. 输入 第一行一个整数Case(Case<=10)表示测试数据

【Codevs1922】骑士共存问题(最小割,二分图最大匹配)

题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击. n<=200,m<=n^2 思路:经典的二分图最大匹配问题,采用黑白点染色的思想. 如果按照相邻点黑白不同染色,可以发现每次跳到的点必定与现在所在点不同色,二分图最大匹配即可. 这里用最小割来解决,因为不能允许任何黑白点之间的任何一条边有流量,符合最小割的思想. 1

Bzoj 4950 (二分图最大匹配)

Description 那是春日里一个天气晴朗的好日子,你准备去见见你的老朋友Patrick,也是你之前的犯罪同伙.Patrick在编程竞赛 上豪赌输掉了一大笔钱,所以他需要再干一票.为此他需要你的帮助,虽然你已经金盆洗手了.你刚开始很不情愿, 因为你一点也不想再回到那条老路上了,但是你觉得听一下他的计划也无伤大雅.在附近的一个仓库里有一批货物, 包含一些贵重的消费性部件,Patrick企图从中尽可能多地偷些东西出来.这意味着要找一条进去的路,弄晕安保人 员,穿过各种各样的激光射线,你懂的,都是

POJ2446_Chessboard(二分图最大匹配)

解题报告 http://blog.csdn.net/juncoder/article/details/38172083 题目传送门 题意: M×N的矩阵,k个点被标记,用2×1的木板最多可以放置多少个. 思路: 把标记的格子除外,链接相邻的两个格子,然后最大匹配出来的是二分图的两倍. c++TLE了,G++1700+过了,理论上匈牙利算法的时间复杂度是n^3,就应该超时,可能数据弱吧. 还有一种建图方式就是建成二分图,将矩阵中的点奇偶分. #include <cstdio> #include

ZOJ 1654 - Place the Robots (二分图最大匹配)

题意:在一个m*n的地图上,有空地,草和墙,其中空地和草能穿透攻击光线,而墙不能.每个机器人能够上下左右攻击,问在地图上最多能放多少个不互相攻击的机器人. 这个题和HDU 1045 -  Fire Net很像.很容易联想到对每个点编号然后互相攻击的点连边再求图的最大独立集,但是这个题数据量太多,超时. 换个思路. 将每个机器人可以攻击到的区域在横和竖方向上分开,这样当横和竖攻击方向都确定时就可以确定一个机器人的放置位置,而在同一个横或竖的攻击区域内不可以再放置机器人. 这样我们把原图上的空地按照