#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
return x*f;
}
const int maxn=20010;
int n,k,m,pa[maxn],rk[maxn];
int findset(int x) {return x==pa[x]?x:findset(pa[x]);}
struct Edge {int u,v,w1,w2;}e[maxn];
int merge(int x,int y) {
x=findset(x);y=findset(y);if(x==y) return 0;
if(rk[x]>rk[y]) swap(x,y);
pa[x]=y;if(rk[x]==rk[y]) rk[y]++;
return 1;
}
int check(int x) {
rep(1,n) pa[i]=i,rk[i]=0;
int tot=0,cnt=n;
rep(1,m) if(e[i].w1<=x) if(merge(e[i].u,e[i].v)) tot++;
cnt-=tot;if(tot<k) return 0;
rep(1,m) if(e[i].w2<=x) if(merge(e[i].u,e[i].v)) cnt--;
return cnt==1;
}
int main() {
n=read();k=read();m=read()-1;
rep(1,m) e[i].u=read(),e[i].v=read(),e[i].w1=read(),e[i].w2=read();
int l=1,r=30000,mid;
while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
printf("%d\n",l);
return 0;
}