Poj_2446 Chessboard -考建图

题目:询问在给定的棋盘中能否用1×2的矩形块填满。

吐槽:由于是二分图专题中,所以毫无悬念地往二分图那边想,而且之前做多校遇到过一个类似的棋盘的题,不过那题目挺难的,是统计连通二分图的个数。

   由于刚开始写二分图,所一用了比较蠢的建图方法。网上说用奇偶建图,而我用正负交替建的。

/************************************************
Author        :DarkTong
Created Time  :2016/7/31 8:27:49
File Name     :Poj_2446.cpp
*************************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>

#define INF 0x3f3f3f3f
#define esp 1e-9
typedef long long LL;
using namespace std;
const int maxn = 1000;
int Left[maxn], w[maxn][maxn], n, m;
bool used[maxn];
bool match(int i)
{
    for(int j=1;j<=n;++j)if(w[j][i]&&!used[j])
    {
        used[j]=true;
        if(!Left[j]||match(Left[j]))
        {
            Left[j]=i;
            return true;
        }
    }
    return false;
}
int hungary()
{
    int res=0;
    memset(Left, 0, sizeof(Left));
    for(int i=1;i<=m;++i)
    {
        memset(used, 0, sizeof(used));
        if(match(i)) res++;
    }
    return res;
}

int vis[maxn][maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int r, c, p;
    while(scanf("%d%d%d", &r, &c, &p)==3)
    {
        memset(vis, 0, sizeof(vis));
        memset(w, 0, sizeof(w));

        int f, u, v, re, lre;
        f=re=1;
        lre=-1;
        for(int i=0;i<p;++i)
        {
            scanf("%d%d", &u, &v);
            vis[v][u]=INF;
        }
        if((r*c-p)&1)
        {
            puts("NO");
            continue;
        }
        //建图
        for(int i=1;i<=r;++i)
        {
            int f = i&1;
            for(int j=(f==1?1:2);j<=c;j+=2)
            {
                if(vis[i][j]==INF) continue;
                vis[i][j]=re++;
            }
            for(int j=(f==1?2:1);j<=c;j+=2)
            {
                if(vis[i][j]==INF) continue;
                vis[i][j]=lre--;
            }
        }
        /*
        for(int i=1;i<=r;++i)
        {
            for(int j=1;j<=c;++j)
                printf("%d ", vis[i][j]);
            puts("");
        }
        */
        for(int i=1;i<=r;++i)
            for(int j=1;j<=c;++j)
            {
                if(vis[i][j]==INF) continue;
                if(i>1)
                {
                    u = vis[i-1][j], v=vis[i][j];
                    if(u!=INF)
                    {
                        if(u>v) swap(u, v);
                        w[-u][v]=1;
                    }
                }
                if(j>1)
                {
                    u = vis[i][j-1], v=vis[i][j];
                    if(u!=INF)
                    {
                        if(u>v) swap(u, v);
                        w[-u][v]=1;
                    }
                }
            }
        n = -lre; m = re;
        n--, m--;
        int ans=hungary();
        if(ans==n&&ans==m) puts("YES");
        else puts("NO");

    }
    return 0;
}

时间: 2024-10-06 21:25:05

Poj_2446 Chessboard -考建图的相关文章

HDU 4370 0 or 1(spfa+思维建图+计算最小环)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4370 题目大意:有一个n*n的矩阵Cij(1<=i,j<=n),要找到矩阵Xij(i<=1,j<=n)满足以下条件: 1.X 12+X 13+...X 1n=1  2.X 1n+X 2n+...X n-1n=1  3.for each i (1<i<n), satisfies ∑X ki (1<=k<=n)=∑X ij (1<=j<=n). 举个例子

HDU 2680 Choose the best route &lt;SPFA算法+反向建图&gt;

Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10690    Accepted Submission(s): 3454 Problem Description One day , Kiki wants to visit one of her friends. As she is liabl

数据结构优化建图总结

数据结构优化建图总结 线段树优化建图 把要连的区间拆成log个点(线段树上的点)连要要连的点上,如果是区间连区间可以建\(\log^2\) 条边 注意,区间连进去和连出来的边顺序不一样,线段树建法也不同 单点连区间(连进去) 由于本质是链接所有根节点,线段树父亲向儿子连零边,保证能到达 区间连单点(连出去)由于所有根节点连这个点,线段树儿子向父亲连零边,能够连出去 此时就需要两颗线段树 例题:CF786B 我会告诉你们用大根堆维护dijkstra还过了前四个点 改longlong看线段树看了半天

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

poj1122 FDNY to the Rescue!(dij+反向建图+输出路径)

题目链接:poj1122 FDNY to the Rescue! 题意:给出矩阵,矩阵中每个元素tij表示从第i个交叉路口到第j个交叉路口所需时间,若tij为-1则表示两交叉路口之间没有直接路径,再给出火警位置所在的交叉路口 和 一个或多个消防站所处的交叉路口位置.输出要求按消防站到火警位置所需时间从小到大排列,输出信息包括消防站位置(初始位置),火警位置(目标位置),所需时间,最短路径上每个交叉路口. 题解:反向建图,从火警位置求一次最短路,求最短路时记录路径,按时间从小到大输出. 1 #in

HDU5772 String problem 最大权闭合图+巧妙建图

题意:自己看吧(不是很好说) 分析: 网络流:最大权闭合子图. 思路如下: 首先将点分为3类 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分) 第二类:原串中的n个点每个点拆出一个点,第i个点权值为 –a[s[i]] (表示要花费) 第三类:对于10种字符拆出10个点,每个点的权值为  -(b[x]-a[x]) 那么我们可以得到一个关系图 ,对于第一类中的点Pij,如果想要选择Pij,你就必须要选中第二类中的点i和j,对于第二类中的点

4205: 卡牌配对 最大流+建图技巧

很明显该题应该是二分图最大匹配,但该题不可能N^2建图,那么我们要怎么办呢?而且有三个属性. 注意到 Ai <= 200 而且 200 以内的质数只有49个,那么我们就可以对着仅有的49个质数下毒手了.很明显如果 Ai 与 Aj 不互质的话, 两者应该有一个共同质因子. B和C同理. 那么我们可以在S集和T集中间建3层质因子的墙,分别为A和B, B和C, C和A. 只有当 Ai 被第 x 个质因子整除, Bi 被第 y 个质因子整除时, 我们从 i 往 P[0][x][y] 连边. 其他同理.

HDU5669 Road 分层最短路+线段树建图

分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ?的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维护整个图, 连边时候找到对应区间,把线段树的节点之间连边.这样可以大大缩减边的规模,然后再跑分层图最短路就可以了. 但是这样建图,每一次加边都要在O(logn)个线段树节点上加边,虽然跑的非常快,但是复杂度仍然是不科学的. 为了解决边的规模的问题,开两棵线段树,连边时候可以新建一个中间节点,在对应区

HDU3572Task Schedule(最大流 ISAP比较快)建图方法不错

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5007    Accepted Submission(s): 1636 Problem Description Our geometry princess XMM has stoped her study in computational geometry t