codeforces 782D Innokenty and a Football League(2-SAT)

D. Innokenty and a Football League
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Innokenty is a president of a new football league in Byteland. The first task he should do is to assign short names to all clubs to be shown on TV next to the score. Of course, the short names should be distinct, and Innokenty wants that all short names consist of three letters.

Each club's full name consist of two words: the team's name and the hometown's name, for example, "DINAMO BYTECITY". Innokenty doesn't want to assign strange short names, so he wants to choose such short names for each club that:

  1. the short name is the same as three first letters of the team's name, for example, for the mentioned club it is "DIN",
  2. or, the first two letters of the short name should be the same as the first two letters of the team's name, while the third letter is the same as the first letter in the hometown's name. For the mentioned club it is "DIB".

Apart from this, there is a rule that if for some club x the second option of short name is chosen, then there should be no club, for which the first option is chosen which is the same as the first option for the club x. For example, if the above mentioned club has short name "DIB", then no club for which the first option is chosen can have short name equal to "DIN". However, it is possible that some club have short name "DIN", where "DI" are the first two letters of the team's name, and "N" is the first letter of hometown's name. Of course, no two teams can have the same short name.

Help Innokenty to choose a short name for each of the teams. If this is impossible, report that. If there are multiple answer, any of them will suit Innokenty. If for some team the two options of short name are equal, then Innokenty will formally think that only one of these options is chosen.

Input

The first line contains a single integer n (1 ≤ n ≤ 1000) — the number of clubs in the league.

Each of the next n lines contains two words — the team's name and the hometown's name for some club. Both team's name and hometown's name consist of uppercase English letters and have length at least 3 and at most 20.

Output

It it is not possible to choose short names and satisfy all constraints, print a single line "NO".

Otherwise, in the first line print "YES". Then print n lines, in each line print the chosen short name for the corresponding club. Print the clubs in the same order as they appeared in input.

If there are multiple answers, print any of them.

Examples
input
2
DINAMO BYTECITY
FOOTBALL MOSCOW
output
YES
DIN
FOO
input
2
DINAMO BYTECITY
DINAMO BITECITY
output
NO
input
3
PLAYFOOTBALL MOSCOW
PLAYVOLLEYBALL SPB
GOGO TECHNOCUP
output
YES
PLM
PLS
GOG
input
3
ABC DEF
ABC EFG
ABD OOO
output
YES
ABD
ABE
ABO
Note

In the first sample Innokenty can choose first option for both clubs.

In the second example it is not possible to choose short names, because it is not possible that one club has first option, and the other has second option if the first options are equal for both clubs.

In the third example Innokenty can choose the second options for the first two clubs, and the first option for the third club.

In the fourth example note that it is possible that the chosen short name for some club x is the same as the first option of another club yif the first options of x and y are different.

每队队名各有两种选择,
第一种选择是:选team's name的前三个字母,记作第一字符串
第二种选择是:选team's name的前两个字母加hometown's name的第一个字母,
              记作第二字符串
*:如果某队的第一字符串在所有第一字符串中出现了两次及以上,则只能选第二字符串。
要求使每队队名互不相同的方案。


由于每队只有两种选择,而且选择之间相互影响,
所以其实可以看作2-SAT问题去做,就很裸了,
设队i为变量xi,选第一字符串xi为0,选第二字符串xi为1,
队名相同即xi与xj冲突,则可连相应的有向边。


由于条件*,所以需要注意一些xi已经有初值了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <bitset>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <algorithm>
#define FOP freopen("data.txt","r",stdin)
#define FOP2 freopen("data1.txt","w",stdout)
#define inf_LL 4223372036854775807
#define inf 0x3f3f3f3f
#define maxn 1010
#define mod 1000000007
#define PI acos(-1.0)
#define LL long long
using namespace std;

int n;
char s1[30], s2[30];
char a[maxn][2][5];

int cot1[150][150][150]; // cot1[i][j][k]记录第一字符串中字符串"ijk"的出现次数
int cot2[150][150][150]; // cot2[i][j][k]记录必须选择的第二字符串中字符串"ijk"的出现次数

// two SAT
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2], c;

bool in[maxn*2]; // 初始赋值

void add_clause(int x, int xval, int y, int yval)
{
    x = x*2 + xval;
    y = y*2 + yval;
    G[x].push_back(y^1);
    G[y].push_back(x^1);
}

bool dfs(int x)
{
    if(mark[x^1] || in[x^1]) return false;
    if(mark[x]) return true;
    mark[x] = true;
    S[c++] = x;
    for(int i = 0; i < G[x].size(); i++)
        if(!dfs(G[x][i])) return false;
    return true;
}

bool solve()
{
    for(int i = 2; i <= n*2; i += 2)
    {
        if(!mark[i] && !mark[i+1])
        {
            c = 0;
            if(!dfs(i))
            {
                while(c > 0) mark[S[--c]] = false; // 恢复
                if(!dfs(i+1)) return false;
            }
        }
    }
    return true;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", s1);
        scanf("%s", s2);
        for(int j = 0; j < 3; j++) a[i][0][j] = s1[j];
        for(int j = 0; j < 2; j++) a[i][1][j] = s1[j];
        a[i][1][2] = s2[0];
    }

    for(int i = 1; i <= n; i++)
    {
        int a1 = a[i][0][0], a2 = a[i][0][1], a3 = a[i][0][2];
        cot1[a1][a2][a3]++;
    }

    bool f = 0;
    for(int i = 1; i <= n; i++)
    {
        int a1 = a[i][0][0], a2 = a[i][0][1], a3 = a[i][0][2];
        if(cot1[a1][a2][a3] > 1)
        {
            a1 = a[i][1][0], a2 = a[i][1][1], a3 = a[i][1][2];
            if(++cot2[a1][a2][a3] > 1) { f = 1; break; }
            in[i*2+1] = true;
        }
    }
    if(f) { printf("NO\n"); return 0; }

     for(int i = 1; i <= n; i++)
        for(int ti = 0; ti < 2; ti++)
            for(int j = i+1; j <= n; j++)
                for(int tj = 0; tj < 2; tj++)
                    if(strcmp(a[i][ti], a[j][tj]) == 0)
                        add_clause(i, ti, j, tj);

    if(!solve()) printf("NO\n");
    else
    {
        printf("YES\n");
        for(int i = 1; i <= n; i++)
        {
            if(mark[i*2]) puts(a[i][0]);
            else puts(a[i][1]);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/christry_stool/article/details/60604286
今日推荐