【CF 515D】 Drazil and Tiles

【CF 515D】 Drazil and Tiles

拓扑的思想 如果满足条件 ‘.’未遍历完之前肯定存在度为1的点(上下左右仅有一个’.’)

遍历到一个1度点u时 将与他连的点v用对应括号括起 此时v也已匹配 入度归零 同时将与v相连的其余点入度减1 不断遍历知道遍历完所有’.’
若能遍历完 则满足条件否则无解或多解
(吐槽一下 原本用的纯粹拓扑思路 想想也是绝对要T的。。后来改换BFS

代码如下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>

using namespace std;

typedef struct Point
{
    int x,y;
}Point;

Point pt[4000000];
int in[2002][2002];
char mp[2002][2002];
int dirx[] = { 0, 0, 1,-1};
int diry[] = { 1,-1, 0, 0};
char ch[] = "><v^";
char st[] = "<>^v";
int m,n;
int tp;

bool iin(int x,int y) {return x > 0 && x <= m && y > 0 && y <= n;}

void rush(int x,int y)
{
    int i,xx,yy,cnt = 0;
    for(i = 0; i < 4; ++i)
    {
        xx = x+dirx[i];
        yy = y+diry[i];
        if(iin(xx,yy) && mp[xx][yy] == '.') cnt++;
    }
    in[x][y] = cnt;
}

bool topo()
{
    int i,j,k,x,y,xx,yy,xxx,yyy,cnt = 0;

    queue <pair<int,int> > q;
    for(j = 0; j <tp; ++j)
    {
        x = pt[j].x;
        y = pt[j].y;
        if(in[x][y] == 1)
        {
            q.push(pair<int,int> (x,y));
            in[x][y] = 0;
        }
    }
    pair <int,int> p;
    while(!q.empty())
    {
        p = q.front();
        q.pop();
        x = p.first;
        y = p.second;
        in[x][y]--;
        for(j = 0; j < 4; ++j)
        {
            xx = x+dirx[j];
            yy = y+diry[j];
            if(iin(xx,yy) && mp[xx][yy] == '.')
            {
                in[xx][yy] = 0;
                mp[xx][yy] = ch[j];
                mp[x][y] = st[j];
                for(k = 0; k < 4; ++k)
                {
                    xxx = xx+dirx[k];
                    yyy = yy+diry[k];
                    if(iin(xxx,yyy) && mp[xxx][yyy] == '.')
                    {
                        rush(xxx,yyy);
                        if(in[xxx][yyy] == 1) q.push(pair<int,int>(xxx,yyy));
                    }
                }
                cnt+=2;
            }
        }
    }
    return cnt == tp;
}

int main()
{
    int i,j;
    scanf("%d %d",&m,&n);
    tp = 0;
    for(i = 1; i <= m; ++i)
    {
        scanf("%s",mp[i]+1);
        for(j = 1; j <= n; ++j)
            if(mp[i][j] == '.')
            {
                pt[tp].x = i;
                pt[tp++].y = j;
                in[i][j] = 0;
                if(iin(i-1,j) && mp[i-1][j] == '.')
                {
                    in[i-1][j]++;
                    in[i][j]++;
                }
                if(iin(i,j-1) && mp[i][j-1] == '.')
                {
                    in[i][j-1]++;
                    in[i][j]++;
                }
            }
    }

    if(topo())
    {
        for(i = 1; i <= m; ++i) printf("%s\n",mp[i]+1);
    }else puts("Not unique");

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值