#include <bits/stdc++.h>
using namespace std;

int N, M, Q;
const int maxM = 2e5;
const int maxN = 5e4 + 5;
int par[maxN];

//定义边
struct edge
{
    int begin, end, cost;
} edges[maxM];

bool cmp(edge x, edge y)
{
    return x.cost < y.cost;
}

//并查集
int get_root(int a)
{ //求根节点
    if (par[a] != a)
    {
        par[a] = get_root(par[a]);
    }
    return par[a];
}

//查询是否在同一集合中
bool query(int a, int b)
{
    return get_root(a) == get_root(b);
}

//合并两个结点
void merge(int a, int b)
{
    par[get_root(a)] = get_root(b);
}

//每次询问都要初始化
void init()
{
    for (int i = 1; i <= N; i++)
    {
        par[i] = i;
    }
}

int solve(int l, int r, int k, int c)
{
    init();
    for (int i = 0; i < M; i++)
    {
        int begin = edges[i].begin;
        int end = edges[i].end;
        int cost = edges[i].cost;

        if (get_root(begin) == get_root(end))
        { //该边的两个结点已经在同一个集合中
            continue;
        }
        else
        {
            merge(begin, end); //合并加边
        }
        //每添加一条边都要判断一下已经满足条件，是就退出
        bool flag = true;
        int parent = 0;
        //检查l到r中模k余c的点是否已经连通
        for (int i = l; i <= r; i++)
        {
            if (i % k == c)
            {
                if (parent == 0)
                {
                    parent = get_root(i);
                }
                else
                {
                    if (parent != get_root(i))
                    { //实际上就是检查这些结点是不是在同一个集合里
                        flag = false;
                        break;
                    }
                }
            }
        }
        if (flag)
        {
            cout << cost << endl; //已经在同一个集合，说明已经连通
            break;
        }
    }
    return 1;
}

int main()
{
    cin >> N >> M >> Q;
    for (int i = 0; i < M; i++)
    {
        cin >> edges[i].begin >> edges[i].end >> edges[i].cost;
    }
    sort(edges, edges + M, cmp); //边从小到大排序
    for (int i = 0; i < Q; i++)
    {
        int l, r, k, c;
        cin >> l >> r >> k >> c;
        solve(l, r, k, c);
    }
    return 0;
}
