There are n villages and there are some roads between them, but there are some roads that can be connected or not to all villages. To save money, deal with unnecessary roads, calculate the minimum total maintenance cost.
--> Use the Kruscal algorithm to generate a Minimum Spanning Tree and output the tree.
[Cpp]
# Include <iostream>
# Include <queue>
# Include <string. h>
Using namespace std;
Const int maxn = 30; // 1 <n <27, 30 is enough
Struct edge // defines the edge Data Type
{
Int v1; // One of the edge endpoints
Int v2; // One of the edge endpoints
Int cost; // monthly maintenance fee
};
Bool operator <(edge e1, edge e2) // defines the priority queue sorting method.
{
Return (e1.cost> e2.cost );
}
Int fa [maxn], height [maxn]; // fa [x] is the father of x, and height [I] is the height of the tree with I as the root (and query the Set)
Int find (int x) // find the root of x (and query the Set)
{
While (fa [x]! = X)
{
X = fa [x];
}
Return x;
}
Bool judge (int x, int y) // determines whether the ring is opened after edge x -- y is added. 0 is returned. If NO, 1 is returned.
{
Int new_x = find (x );
Int new_y = find (y );
If (new_x = new_y) return 0; // The Ring is formed.
Else // No ring
{
If (height [new_x]> height [new_y]) fa [new_y] = new_x;
Else if (height [new_x] = height [new_y])
{
Fa [new_y] = new_x;
Height [new_x] ++;
}
Else fa [new_x] = new_y;
Return 1;
}
}
Bool G [maxn] [maxn]; // uses an adjacent matrix to store graphs.
Bool vis [maxn], viss [maxn]; // vis and viss are used to determine whether the village has passed
Int n; // n villages
Void dfs (int I) // depth-first traversal to modify a connected Block
{
Vis [I] = 1;
Int j;
For (j = 1; j <= n; j ++)
If (G [I] [j] = 1 & vis [j] = 0)
Dfs (j );
Return;
}
Bool is_ OK () // determine whether the village is connected
{
Memset (viss, 0, sizeof (viss ));
Int count = 0, OK = 1, I;
For (I = 1; I <= n; I ++)
{
If (viss [I] = 0)
{
Dfs (I );
Count ++;
If (count> = 2)
{
OK = 0;
Break;
}
}
}
If (OK) return 1;
Else return 0;
}
Int main ()
{
Int I, j;
While (cin> n)
{
If (n = 0) return 0;
Char c1, c2;
Int num1, num2;
For (I = 1; I <= n; I ++)
{
Fa [I] = I;
Height [I] = 1;
}
Priority_queue <edge> qu; // use the priority queue to get the path with the minimum fee
Edge newnode;
Memset (G, 0, sizeof (G ));
For (I = 1; I <= n-1; I ++)
{
Cin> c1> num1;
For (j = 1; j <= num1; j ++)
{
Cin> c2> num2;
G [(int) (c1-'A') + 1] [(int) (c2-'A') + 1] = 1; // set A, B, c... to 1, 2, 3...
G [(int) (c2-'A') + 1] [(int) (c1-'A') + 1] = 1;
Newnode. v1 = (int) (c1-'A') + 1;
Newnode. v2 = (int) (c2-'A') + 1;
Newnode. cost = num2;
Qu. push (newnode); // enter the column
}
}
Int sum = 0; // total fee
Int OK = 0; // indicates whether the entire island is connected.
Memset (vis, 0, sizeof (vis ));
While (! OK &&! Qu. empty ())
{
If (judge (qu. top (). v1, qu. top (). v2) // use and check the set to determine whether the edge will form a ring or not.
{
OK = 0;
Vis [qu. top (). v1] = 1; // mark the two villages as walking
Vis [qu. top (). v2] = 1;
Sum + = qu. top (). cost; // The total fee.
If (is_ OK () OK = 1; // Add the edge to determine whether all villages are connected
}
Qu. pop ();
}
Cout <sum <endl;
}
Return 0;
}