Equivalent Sets
Time Limit: 12000/4000 MS (Java/others) memory limit: 104857/104857 K (Java/Others)
Total submission (s): 550 accepted submission (s): 81
Problem description
To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is a subset of A, so finally we got that these two sets are equivalent.You are to prove N sets are equivalent, using the method above: in each step you can prove a set X is a subset of another set Y, and there are also some sets that are already proven to be subsets of some other sets.Now you want to know the minimum steps needed to get the problem proved.
Input
The input file contains multiple test cases, in each case, the first line contains two integers N <= 20000 and M <= 50000.Next M lines, each line contains two integers X, Y, means set X in a subset of set Y.
Output
For each case, output a single integer: the minimum steps needed.
Sample Input
4 03 21 21 3
Sample output
42HintCase 2: First prove set 2 is a subset of set 1 and then prove set 3 is a subset of set 1.
Source
HNU
My graph theory is still in the cainiao stage. At the time of the competition, I saw that it was a strongly connected question, but the tarjon algorithm was not typed yet, so I found a template on the Internet... I admit my shame...
You can add at least a few sides to make the directed graph strongly connected. After the point is reduced, the number of points with a zero degree and zero degree of input can be taken to the maximum value, of course, the issue is strongly connected. I did it once because of this wa, but I don't care about it because it doesn't happen to me... Poj similar question 2186 popular cows is also the original question of the copied Template
The AC code should be someone else's code:
# Include <iostream>
Using namespace STD;
Int dfn [20010], low [20010], times, C, S [20010], s [20010], top;
Boolean in [20010];
Struct list
{
Int V; list * next;
};
List * head [20010], * rear [20010];
Int chudu [20010], Indu [20010];
Void Tarjan (INT v)/* Tarjan evaluate the strongly connected component of the graph */
{
Dfn [v] = low [v] = ++ times;
S [top ++] = V;
In [v] = true;
For (list * P = head [v]; P! = NULL; P = p-> next)
If (! Dfn [p-> V])
{
Tarjan (p-> V );
If (low [p-> V] <low [v])
Low [v] = low [p-> V];
}
Else if (in [p-> V] & low [p-> V] <low [v])
Low [v] = low [p-> V];
If (low [v] = dfn [v])
{
C ++;
Do
{
V = s [-- top];
In [v] = false;
S [v] = C;/* scale down a graph to mark points belonging to the same strongly connected component */
} While (low [v]! = Dfn [v]);
}
}
Int main ()
{
Int n, m, I, A, B;
While (CIN> N> m)
{
Memset (Head, 0, sizeof (INT) * 20010 );
Memset (rear, 0, sizeof (INT) * 20010 );
Memset (S, 0, sizeof (INT) * 20010 );
Top = 0;
For (I = 0; I <m; I ++)/* adjacent table Storage Relation Diagram */
{
Scanf ("% d", & A, & B );
If (rear [a]! = NULL)
{
Rear [a]-> next = new list;
Rear [a] = rear [a]-> next;
}
Else
Head [a] = rear [a] = new list;
Rear [a]-> next = NULL;
Rear [a]-> V = B;
}
Times = 0; C = 0;
Memset (dfn, 0, sizeof (INT) * 20010 );
Memset (low, 0, sizeof (INT) * 20010 );
Memset (in, 0, sizeof (bool ));
For (I = 1; I <= N; I ++)
If (! Dfn [I])
Tarjan (I );
Memset (chudu, 0, sizeof (chudu ));
Memset (Indu, 0, sizeof (Indu ));
For (I = 1; I <= N; I ++)/* calculate the degree of exit of each vertex after the thumbnail */
For (list * P = head [I]; P! = NULL; P = p-> next)
If (s [I]! = S [p-> V])
Chudu [s [I] = 1, Indu [s [p-> V] = 1;
A = B = 0;
For (I = 1; I <= C; I ++)
If (! Chudu [I])
A ++;
For (I = 1; I <= C; I ++)
If (! Indu [I]) B ++;
If (C = 1) printf ("0 \ n ");
// Printf ("% d \ n", a, B );
Else
Printf ("% d \ n", A> B? A: B );
}
Return 0;
}
Hnu Problem Solving report (still not readable)
Give a directed graph and find the minimum number of edges to make the graph become a strongly connected graph.
First, if the graph itself is strongly connected, the answer is 0.
Otherwise, scale down the strongly connected component to change the graph to a dag, and then calculate the number of points with a 0 degree of access and a 0 degree of exit. The maximum value is the answer.
Difficulty:★★
# Include <stdio. h>
# Include <string. h>
Const int maxn = 20001;
Const long maxm = 50001;
Long Head [2] [maxn], next [2] [maxm], edge [2] [maxm];
Int N;
Long m;
Int A [maxn], B [maxn], C [maxn];
Int K;
Long I, j, TOT;
Void search (const int vtx ){
B [vtx] = 1;
For (long I = head [0] [vtx]; I; I = next [0] [I])
If (! B [edge [0] [I]) Search (edge [0] [I]);
A [++ tot] = vtx;
}
Void _ search (const int vtx ){
B [vtx] = tot;
For (long I = head [1] [vtx]; I; I = next [1] [I])
If (! B [edge [1] [I]) _ search (edge [1] [I]);
}
Int main (){
While (scanf ("% d % lD", & N, & M) = 2 ){
Memset (Head, 0, sizeof (head ));
For (I = 1; I <= m; ++ I ){
Scanf ("% LD % d", & J, & K );
Edge [0] [I] = K;
Next [0] [I] = head [0] [J];
Head [0] [J] = I;
Edge [1] [I] = J;
Next [1] [I] = head [1] [k];
Head [1] [k] = I;
}
Memset (B, 0, sizeof (B ));
For (TOT = 0, I = 1; I <= N; ++ I)
If (! B [I]) Search (I );
Memset (B, 0, sizeof (B ));
For (TOT = 0, I = N; I; -- I)
If (! B [A [I]) {
++ Tot;
_ Search (A [I]);
}
If (TOT <= 1 ){
Puts ("0 ");
Continue;
}
M = tot;
Memset (A, 0, sizeof ());
Memset (C, 0, sizeof (c ));
For (TOT = 0, I = 1; I <= N; ++ I)
For (k = B [I], j = head [0] [I]; j = next [0] [J])
If (K! = B [edge [0] [J]) {
+ A [B [edge [0] [J];
++ C [k];
}
For (TOT = n = 0, I = 1; I <= m; ++ I ){
If (! A [I]) ++ tot;
If (! C [I]) ++ N;
}
Printf ("% LD \ n", TOT> n? TOT: N );
}
Return 0;
}