2018暑假校内第一次比赛C题

Ninja Map
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:524288KB
Total submit users: 13, Accepted users: 8
Problem 14106 : Special judge
Problem description
Intersections of Crossing Path City are aligned to a grid. There are N east-west streets which are numbered from 1 to N, from north to south. There are also N north-south streets which are numbered from 1 to N, from west to east. Every pair of east-west and north-south streets has an intersection; therefore there are N2 intersections which are numbered from 1 to N2.
Surprisingly, all of the residents in the city are Ninja. To prevent outsiders from knowing their locations, the numbering of intersections is shuffled.
You know the connections between the intersections and try to deduce their positions from the information. If there are more than one possible set of positions, you can output any of them.
 
Input
The input consists of a single test case formatted as follows.
N
a1b1
...
a2N2-2Nb2N2-2N
The first line consists of an integer N(2 ≤ N ≤ 100). The following 2N2-2N lines represent connections between intersections. The (i+1)-th line consists of two integers ai and bi(1 ≤ ai,bi ≤ N2,ai ≠ bi), which represent that the ai-th and bi-th intersections are adjacent. More precisely, let's denote by (r,c) the intersection of the r-th east-west street and the c-th north-south street. If the intersection number of (r,c) is aifor some r and c, then the intersection number of either (r-1,c),(r+1,c) ,(r,c-1) or (r,c+1) must be bi. All inputs of adjacencies are different, i.e., (ai,bi) ≠ (aj,bj) and (ai,bi) ≠ (bj,aj) for all 1 ≤ i < j ≤ 2N2-2N. This means that you are given information of all adjacencies on the grid.
The input is guaranteed to describe a valid map.
 
Output
Print a possible set of positions of the intersections. More precisely, the output consists of N lines each of which has space-separated N integers. The c-th integer of the r-th line should be the intersection number of (r,c).
If there are more than one possible set of positions, you can output any of them.
 
Sample Input
Sample Input 1
3
1 2 
4 7
8 6
2 3
8 9
5 3
4 6
5 6
7 8
1 4
2 6
5 9

Sample Input 2
4
12 1
3 8
10 7
13 14
8 2
9 12
6 14
11 3
3 13
1 10
11 15
4 15
4 9
14 10
5 7
2 5
6 1
14 5
16 11
15 6
15 13
9 6
16 4
13 2
Sample Output
Output for Sample Input 1
7 4 1
8 6 2
9 5 3

Output for Sample Input 2
8 2 5 7
3 13 14 10
11 15 6 1
16 4 9 12
Judge Tips
For the first test case,The following output will also be accepted.

1 2 3
4 6 5
7 8 9
 
Problem Source
JAG Practice Contest for ACM-ICPC Asia Regional 2017, AtCoder, 2017-09-24

题意:给定一个n * n的矩阵,以及矩阵内的相邻关系,任意输出一种符合情况的矩阵

题解:首先统计每个点的度数,初始情况下度数为2的一定是四个顶点的其中一个,我们任选一个点放在右上角。

然后我们将其入队,对于队列, 当其非空时,取队首元素,浏览它的相邻点中没有被访问过的点,若没有被访问,度数减一,如果度数小于等于2,则将其入队并标记。

对于任意一个出队的点,有三种情况

第一种,其相邻点有两个没有被标记且其中有一个度数小于等于2

第二种,其相邻点有两个没有被标记且其中两个度数小于等于2

第三红,其相邻点有一个没有被标记且其度数小于等于2

以上三种可以归纳成两种情况

1、当前将一个节点安置在出队元素周围

2、当前将两个节点安置在出队元素周围

因为我设置的是优先安置在下方,故只有一个节点时,先看下方能否放置,不能则放置在右方

当有两个节点时,看当前位置右上第一个顶点跟两个顶点中的哪一个有连边,有连边的点则放置在右边,另一个点放置在下边

以上

AC代码

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
#include <queue>

using namespace std;

const int maxn = 11111, maxm = 111111;
int a[maxn][maxn] = {0}, vis[maxm] = {0}, num[maxm] = {0}, x[maxm], y[maxm], vis1[maxm];
vector<int> s[maxm];

int main(){
    int n, x1, y1, now1, x2, y2;
    scanf("%d", &n);
    for(int i = 0; i < maxm; i++){
        vis[i] = 0;
        num[i] = 0;
        vis1[i] = 0;
        s[i].clear();
    }
//    for(int i = 0; i < maxn; i++)
//        for(int j = 0; j < maxn; j++)
//            a[i][j] = 0;
    for(int i = 0; i < 2 * n * (n - 1); i++){
        scanf("%d %d", &x1, &y1);
        s[x1].push_back(y1);
        s[y1].push_back(x1);
        num[x1]++;
        num[y1]++;
    }
    for(int i = 1; i <= n * n; i++){
        if(num[i] == 2){
            now1 = i;
            break;
        }
    }
    queue<int> q;
    q.push(now1);
    x[now1] = 1;
    y[now1] = 1;
    vis[now1] = 1;
    a[1][1] = now1;
    while(!q.empty()){
        x1 = q.front();
        q.pop();
        vector<int> tmp;
        tmp.clear();
        for(int i = 0; i < s[x1].size(); i++){
            int v = s[x1][i];
            if(vis[v] == 0){
                num[v]--;
                if(num[v] <= 2){
                    tmp.push_back(v);
                    vis[v] = 1;
                }
            }
        }
        if(tmp.size() == 2){
            int v1 = x[x1] + 1;
            int v2 = y[x1] - 1;
            int v3 = x[x1] - 1;
            int v4 = y[x1] + 1;
            if(a[v1][v2]==0&&a[v3][v4]==0){
                x[tmp[0]] = x[x1] + 1;
                y[tmp[0]] = y[x1];
                x[tmp[1]] = x[x1];
                y[tmp[1]] = y[x1] + 1;
                a[x[tmp[0]]][y[tmp[0]]] = tmp[0];
                a[x[tmp[1]]][y[tmp[1]]] = tmp[1];
            }
            else{
                if(a[v3][v4] != 0){
                    int v5 = a[v3][v4];
                    for(int j = 0; j < s[v5].size(); j++){
                        int v6 = s[v5][j];
                        if(tmp[0] == v6){
                            x[tmp[0]] = x[x1];
                            y[tmp[0]] = y[x1] + 1;
                            x[tmp[1]] = x[x1] + 1;
                            y[tmp[1]] = y[x1];
                            a[x[tmp[0]]][y[tmp[0]]] = tmp[0];
                            a[x[tmp[1]]][y[tmp[1]]] = tmp[1];
                        }
                        if(tmp[1] == v6){
                            x[tmp[0]] = x[x1] + 1;
                            y[tmp[0]] = y[x1];
                            x[tmp[1]] = x[x1];
                            y[tmp[1]] = y[x1] + 1;
                            a[x[tmp[0]]][y[tmp[0]]] = tmp[0];
                            a[x[tmp[1]]][y[tmp[1]]] = tmp[1];
                        }
                    }
                }
                else{
                    int v5 = a[v1][v2];
                    for(int j = 0; j < s[v5].size(); j++){
                        int v6 = s[v5][j];
                        if(tmp[0] == v6){
                            x[tmp[0]] = x[x1] + 1;
                            y[tmp[0]] = y[x1];
                            x[tmp[1]] = x[x1];
                            y[tmp[1]] = y[x1] + 1;
                            a[x[tmp[0]]][y[tmp[0]]] = tmp[0];
                            a[x[tmp[1]]][y[tmp[1]]] = tmp[1];
                        }
                        if(tmp[1] == v6){
                            x[tmp[0]] = x[x1];
                            y[tmp[0]] = y[x1] + 1;
                            x[tmp[1]] = x[x1] + 1;
                            y[tmp[1]] = y[x1];
                            a[x[tmp[0]]][y[tmp[0]]] = tmp[0];
                            a[x[tmp[1]]][y[tmp[1]]] = tmp[1];
                        }
                    }
                }
            }
            q.push(a[x[x1]+1][y[x1]]);
            q.push(a[x[x1]][y[x1]+1]);
        }
        if(tmp.size() == 1){
            x[tmp[0]] = x[x1];
            y[tmp[0]] = y[x1];
            if(x[tmp[0]] < n && a[x[tmp[0]]+1][y[tmp[0]]] == 0)
                x[tmp[0]]++;
            else
                y[tmp[0]]++;
            a[x[tmp[0]]][y[tmp[0]]] = tmp[0];
            q.push(tmp[0]);
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(j == 1)
                printf("%d", a[i][j]);
            else
                printf(" %d", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值