#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 26;
// 成员
typedef struct Person
{
    char name[5]; //名字
    int weight;   //权重
    int parent;   //parent保存集合的根节点下标,根节点的parent保存集合成员个数
    Person()
    {
        parent = -1;
        weight = 0;
    }
} Person;
// 帮派
typedef struct gang
{
    char head[5]; //头目
    int number;   //成员数量
} gang;

Person p[N];
int sum[N]; //保存每个集合的总权重

//字典排序函数
bool cmp(gang a, gang b)
{
    return strcmp(a.head, b.head) < 0;
}
//并查集函数
int FindRoot(int x)
{
    int a = x;
    while (p[x].parent >= 0)
    {
        x = p[x].parent;
    }
    while (p[a].parent >= 0)
    {
        int z = a;
        a = p[a].parent;
        p[z].parent = x;
    }
    return x;
}
void Union(int no1, int no2, int weight)
{
    int p1 = FindRoot(no1), p2 = FindRoot(no2);
    //如果是同一个集合也要加上权重
    if (p1 == p2)
    {
        sum[p1] += weight;
        return;
    } 
    if (p[p1].parent > p[p2].parent)
    {
        p[p2].parent += p[p1].parent;
        p[p1].parent = p2;
        sum[p2] = sum[p1] + sum[p2] + weight;
    }else{
         //根结点p1的parent保存集合成员个数
        p[p1].parent += p[p2].parent;
        //p2的parent保存集合的根节点下标
        p[p2].parent = p1;
        //合并的过程,顺便加上集合的总权重
        sum[p1] = sum[p1] + sum[p2] + weight;
    }
}
int main()
{
    int n, k;
    while (scanf("%d%d", &n, &k) != EOF)
    {
        getchar(); //用于消除缓冲区回车防止字符串输入出错
        int i;
        memset(sum, 0, sizeof(sum));
        while (n--)
        {
            char name1[5], name2[5];
            int weight, no1, no2;
            scanf("%s%s%d", name1, name2, &weight);
            getchar();                                  //用于消除缓冲区同上
            no1 = name1[0] - 'A', no2 = name2[0] - 'A'; //由名字找到这个人下标
            //保存该人的名字,每遇到这个人就要加上一次权重
            strcpy(p[no1].name, name1), p[no1].weight += weight;
            strcpy(p[no2].name, name2), p[no2].weight += weight;
            //合并有联系的人
            Union(no1, no2, weight);
        }
        int ans = 0; //保存帮派数目
        gang g[10];  //结果数组,26个人帮派最多有8个,10的数组够了
        for (i = 0; i < N; i++)
        {
            if (p[i].parent < -2 && sum[i] > k)
            {                                 //人数超过2人,总权重大于k则为帮派
                g[ans].number = -p[i].parent; //保存下帮派人数
                int parent = i;               //根节点存一下,其实有点多余,可以直接用i
                int max = i;                  //权重最大者下标,初始为根节点
                for (int j = 0; j < N; j++)
                {
                    if (FindRoot(j) == parent && p[j].weight > p[max].weight)
                        max = j; //如果属于此集合且权重更大,替换一下
                }
                strcpy(g[ans].head, p[max].name); //把头目名字存进来
                ans++;                            //接着存下一个帮派
            }
        }
        printf("%d\n", ans);   //输出帮派数目
        sort(g, g + ans, cmp); //按字典sort一下
        for (i = 0; i < ans; i++)
            printf("%s %d\n", g[i].head, g[i].number); //输出头目名字和帮派人数
    }
    return 0;
}