Mike and his young
daughter Jesse are playing a new card game meant for kids. The rules are quite
simple, each player is dealt a hand of cards. Each card has one picture on each
side. They take turns playing cards and the first one to run out of cards is
the winner.
A player’s turn consists
of picking a subset of cards from their hand and laying them on the table. The
only rule is that the cards must be placed on the table such that no two cards
are showing the same picture.
Mike thought this was a
very appropriate game to play with his kid because of the simple rules. Mike
also liked this game because finding the best strategy is an algorithmically
interesting challenge!
Help Mike determine if he
can play his entire hand on his first round.
Input. The first line contains a single positive integer t (t
≤ 10) indicating the number of test cases. Each test case begins with a
single integer n (1 ≤ n ≤ 50 000) denoting the number of
cards in Mike's hand. Following this are n
lines, each describing a card in Mike’s hand.
The pictures on the cards are represented by integers. The i-th card is given by two integers pi, qi where 1 ≤ pi,
qi ≤ 2n.
Output. For each test case you
should output a single line with the word possible
if it is possible for Mike to play his entire hand in one turn, or impossible if Mike cannot play his
entire hand in one turn.
Sample
input |
Sample
output |
3 3 1 2 1 3 2 3 3 1 2 1 2 1 2 1 1 1 |
possible impossible possible |
graphs
– cycles, DSU
Algorithm analysis
Each picture
depicted on the cards will be assigned one vertex of the graph. Each card will
be assigned an undirected edge (that connects the vertices corresponding to the pictures on the
sides of the card). The resulting graph may be disconnected.
The answer to
the problem will be possible if each connected component of the graph
contains at most one cycle. Finding the connected components and counting the number of cycles in them
can be done using a system
of disjoint sets.
Example
Consider four
cards. In yellow we denote the sides of the cards with which they will lie up.
Let’s mark the edge
of the graph with a picture with which the corresponding card will lie up.
Consider the
case with two connected components:
Algorithm realization
Define arrays for data processing. The dsu array is used for the
disjoint set system. If i is a representative of a set, then has_cycle[i]
contains information
about the number of cycles in it:
·
has_cycle[i] =
0, no cycles;
·
has_cycle[i] = 1,
one cycle;
·
has_cycle[i] > 1, more than one cycle;
#define MAX 50010
int dsu[2*MAX], has_cycle[2*MAX];
The function Repr returns a representative of
the set that contains vertex n.
int Repr(int n)
{
if (n == dsu[n])
return n;
return dsu[n]
= Repr(dsu[n]);
}
The function Union joins the sets containing the
vertices x and y.
void Union(int x, int y)
{
int x1 =
Repr(x), y1 = Repr(y);
If x and y already belong to the same connected
component (they have the same representative), and there is an edge (x, y),
then another cycle is formed. Add 1 to the number of cycles of their representative
(x1 is a representative of x and y).
if (x1 == y1)
has_cycle[x1]++;
If x and y belong to different connected
components, and y1 becomes
a representative of the set, then we add the number of cycles for x1 to the number of cycles for y1.
else
{
dsu[x1] = y1;
has_cycle[y1] += has_cycle[x1];
}
}
The main part of the program. Read the input data.
scanf("%d",&tests);
while (tests--)
{
scanf("%d",&n);
Initialize the system of disjoint sets.
for(i = 1; i <= 2*n; i++)
{
dsu[i] = i;
has_cycle[i] = 0;
}
Construct a system of disjoint sets.
for (i = 0; i < n; i++)
{
scanf("%d
%d",&p,&q);
Union(p,q);
}
Check if at least one connected component contains more than one cycle.
for (i = 1; i <= 2*n; i++)
if
(has_cycle[i] > 1) break;
Print the answer.
printf("%s\n",((i
<= 2 * n) ? "impossible" : "possible"));
}
Java realization
import java.util.*;
//import java.io.*;
public class Main
{
static int dsu[], has_cycle[];
static int Repr(int n)
{
if (n == dsu[n]) return n;
return dsu[n] = Repr(dsu[n]);
}
static void Union(int x, int y)
{
int x1 = Repr(x), y1 = Repr(y);
if (x1 == y1)
has_cycle[x1]++;
else
{
dsu[x1] = y1;
has_cycle[y1] += has_cycle[x1];
}
}
public static void main(String[] args) //throws IOException
{
Scanner con = new Scanner(System.in);
//Scanner con = new Scanner(new FileReader
("7538.in"));
int tests = con.nextInt();
while(tests-- > 0)
{
int i, n = con.nextInt();
dsu = new int[2*n+2];
has_cycle = new int[2*n+2];
for(i = 1; i <= 2*n; i++)
{
dsu[i] = i;
has_cycle[i] = 0;
}
for (i = 0; i < n; i++)
{
int p = con.nextInt();
int q = con.nextInt();
Union(p,q);
}
for (i = 1; i <= 2*n; i++)
if (has_cycle[i] > 1) break;
if (i <= 2 * n)
System.out.println("impossible");
else
System.out.println("possible");
}
con.close();
}
}