#include<iostream>
#include<vector>
#include<map>
#include<utility>
#include<queue>
using namespace std;
struct Node{
int ID, cont;
bool SDN_Node;
map<int, vector<int>> Children;
map<int, vector<int>> Table;
};
struct Flow{
int ID, Src_Node, Dst_Node, Size;
};
class Data{
public:
Data();
void output();
void input();
void initialize();
void BFS();
void algorithm();
private:
int Nodes, SDN_Nodes, Dsts, Links_num, Pairs;
vector<int> SDN_ary;
vector<int> Dsts_ary;
vector<vector<int>> Links_ary;
vector<Flow> Flow_ary;
vector<Node> Node_ary;
void update(bool,int,int,int,int);
bool getSDN(int);
bool find(int,int,int);
};
int main(){
Data a;
a.initialize();
a.input();
a.BFS();
a.algorithm();
a.output();
}
Data::Data(){
cin >> Nodes >> SDN_Nodes >> Dsts >> Links_num >> Pairs;
}
void Data::initialize(){
Links_ary.resize(Nodes, vector<int>(Nodes, 0));
SDN_ary.resize(SDN_Nodes, 0);
Dsts_ary.resize(Dsts, 0);
Flow_ary.resize(Pairs);
Node_ary.resize(Nodes);
}
void Data::input(){
int LinkID, Node1, Node2;
for (auto it = SDN_ary.begin(); it != SDN_ary.end(); it++){
cin >> *it;
}
for (auto jt = Dsts_ary.begin(); jt != Dsts_ary.end(); jt++){
cin >> *jt;
}
for (int i=0; i < Links_num; i++){
cin >> LinkID >> Node1 >> Node2;
Links_ary[Node1][Node2] = 1;
Links_ary[Node2][Node1] = 1;
}
for (auto lt = Flow_ary.begin(); lt != Flow_ary.end(); lt++){
Flow tmp;
cin >> tmp.ID >> tmp.Src_Node >> tmp.Dst_Node >> tmp.Size;
*lt = tmp;
}
}
void Data::output(){
// for (auto row:Links_ary){
// for (auto val:row){
// cout << val << " ";
// }
// cout << endl;
// }
for (auto x:Node_ary){
cout << x.ID << endl;
for (auto y:x.Table){
cout << y.first << " ";
for (auto z:y.second){
cout << z ;
if (x.SDN_Node){
double SDN_size = y.second.size();
double Proportion = 100.0 / SDN_size;
cout << " " << Proportion << "% ";
}
}
cout << endl;
}
}
// cout << endl;
// for (auto v:Node_ary){
// cout << v.ID << endl;
// for (auto vv : v.Children){
// cout << vv.first << " : " ;
// for (auto vvv : vv.second){
// cout << vvv << " ";
// }
// cout << endl;
// }
// }
}
void Data::algorithm(){
for (auto DSTS : Dsts_ary){
for (auto SDN : SDN_ary){
for (int i = 0; i < Nodes; i++){
if (Links_ary[SDN][i] == 1 && !find(SDN, DSTS, i) && !(Links_ary[i][DSTS] == 1) ){
Node_ary[SDN].Table[DSTS].push_back(i);
Node_ary[i].Children[DSTS].push_back(SDN);
}
}
}
}
}
bool Data::find(int SDN, int DSTS, int Find_ID){
auto children_tmp = Node_ary[SDN].Children[DSTS];
auto table_tmp = Node_ary[SDN].Table[DSTS];
for (auto i = children_tmp.begin(); i != children_tmp.end(); i++){
if (*i == Find_ID){
return true;
}
}
for (auto j = table_tmp.begin(); j != table_tmp.end(); j++){
if (*j == Find_ID){
return true;
}
}
if (table_tmp.size() > 5){
return true;
}
return false;
}
void Data::BFS(){
for (auto current : Dsts_ary){
queue<int> q;
bool visited[Nodes] = {false};
visited[current] = true;
q.push(current);
update(true, current, current, current, 0);
while (!q.empty()){
int now_node = q.front();
q.pop();
for (int i = 0; i < Nodes; i++){
int link = Links_ary[now_node][i];
if ( link != 0 && !(visited[i]) ){
q.push(i);
visited[i] = true;
int Cont = Node_ary[now_node].cont;
update( true, i, current, now_node, (Cont+1) );
}
}
}
}
}
void Data::update(bool state,int ID, int dis_ID, int par_ID, int cont){
if (state){
Node_ary[ID].ID = ID;
Node_ary[ID].SDN_Node = getSDN(ID);
Node_ary[ID].cont = cont;
Node_ary[ID].Table[dis_ID].push_back(par_ID);
Node_ary[par_ID].Children[dis_ID].push_back(ID);
}
}
bool Data::getSDN(int ID){
for (auto &it : SDN_ary){
if (it == ID){
return true;
}
}
return false;
}