// Smile please :)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cassert>
#include <cctype>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <string>
#include <iomanip>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
#include <list>
#include <bitset>
#include <climits>
//#include <unordered_map>
//#include <unordered_set>
using namespace std;

//#undef KVARK_DEBUG

#ifdef KVARK_DEBUG
	#include "../h/debug.h"
#else
#define dbg(...) (void(1));
#define dbg2(...) (void(1));
#define dbg3(...) (void(1));
#define dbg4(...) (void(1));
#define dbg5(...) (void(1));
#define dbgp(...) (void(1));
#define dbg_arr(...) (void(1));
#define dbg_vec(...) (void(1));
#endif

typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef pair<double, int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<vector<int> > vvi;
typedef vector<vector<pii> > vvpii;
typedef vector<vector<long long> > vvl;
typedef vector<long long> vl;
typedef long long int llint;

#define ALL(v) (v.begin()), (v.end())
#define SZ(v) ((int)((v).size()))
#define endl "\n"

void task();

int main(){
#ifdef KVARK
	freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	srand(time(0));
#endif
//	ios_base::sync_with_stdio(0);

	task();

#ifdef KVARK_DEBUG
	my_debug::printProcessInfo();
#endif
	return 0;
}
const int INF = 0x3f3f3f3f;
const int N = 2e5+10;
const int M = 2e5+10;

struct Rib {
	int to;
	llint w;
};

struct V {
	vector<Rib> next;
	int fast_link;
	int p;
	llint w;
};

int n, q;
V g[N];
int tin[N];
int tout[N];
int t;
map<pii, int> ribs_id;
map<pii, llint> ribs_w;
int id_to_v[N];

inline void dfs1(int v, int p) {
	if (p != -1) {
		id_to_v[ribs_id[pii{p, v}]] = v;
		g[v].p = p;
		g[v].w = ribs_w[pii{p, v}];
	}
	tin[v] = t++;

	g[v].fast_link = v;

	for (Rib r: g[v].next) if (r.to != p)
		dfs1(r.to, v);

	tout[v] = t++;
}

inline bool is_upper(int a, int b) {
	return tin[a] <= tin[b]  && tin[b] <= tout[a] &&
				 tin[a] <= tout[b] && tout[b] <= tout[a];
}

inline int find(int v) {
	if (v == 0)
		return 0;
	if (g[v].w > 1)
		return v;
	return g[v].fast_link = find(g[v].fast_link == v ? g[v].p : g[v].fast_link);
}

inline void go1(int a, int b, llint &w) {
	while (w > 0 && !is_upper(a, b)) {
		if (g[a].w != 1) {
			w /= g[a].w;
			a = g[a].p;
		} else {
			a = find(a);
		}
	}
}

inline void solve(int a, int b, llint &w) {
	if (w == 0)
		return;
	go1(a, b, w);
	go1(b, a, w);
}

inline void change(int id, llint c) {
	int v = id_to_v[id];
	g[v].w = c;
}

void task() {
	scanf("%d %d", &n, &q);
	for (int i = 0; i < n - 1; ++i) {
		int a, b;
		llint w;
		scanf("%d %d %I64d", &a, &b, &w);
		--a, --b;
		ribs_id[pii{a,b}] = i;
		ribs_id[pii{b,a}] = i;
		ribs_w[pii{a, b}] = w;
		ribs_w[pii{b, a}] = w;
		g[a].next.push_back(Rib{b, w});
		g[b].next.push_back(Rib{a, w});
	}
	dfs1(0, -1);

	while (q--) {
		int cmd;
		scanf("%d", &cmd);
		if (cmd == 1) {
			int a, b;
			llint w;
			scanf("%d %d %I64d", &a, &b, &w);
			--a, --b;
			if (a == b) {
				printf("%I64d\n", w);
				continue;
			}
			solve(a, b, w);
			printf("%I64d\n", w);
		} else if (cmd == 2) {
			int p;
			llint c;
			scanf("%d %I64d", &p, &c);
			--p;
			change(p, c);
		}
	}
}


// Smile please :)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cassert>
#include <cctype>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <string>
#include <iomanip>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
#include <list>
#include <bitset>
#include <climits>
//#include <unordered_map>
//#include <unordered_set>
using namespace std;

//#undef KVARK_DEBUG

#ifdef KVARK_DEBUG
	#include "../h/debug.h"
#else
#define dbg(...) (void(1));
#define dbg2(...) (void(1));
#define dbg3(...) (void(1));
#define dbg4(...) (void(1));
#define dbg5(...) (void(1));
#define dbgp(...) (void(1));
#define dbg_arr(...) (void(1));
#define dbg_vec(...) (void(1));
#endif

typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef pair<double, int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<vector<int> > vvi;
typedef vector<vector<pii> > vvpii;
typedef vector<vector<long long> > vvl;
typedef vector<long long> vl;
typedef long long int llint;

#define ALL(v) (v.begin()), (v.end())
#define SZ(v) ((int)((v).size()))
#define endl "\n"

void task();

int main(){
#ifdef KVARK
	freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	srand(time(0));
#endif
//	ios_base::sync_with_stdio(0);

	task();

#ifdef KVARK_DEBUG
	my_debug::printProcessInfo();
#endif
	return 0;
}
const int INF = 0x3f3f3f3f;
const int N = 2e5+10;
const int M = 2e5+10;

struct Rib {
	int to;
	llint w;
};

struct V {
	vector<Rib> next;
	int up450;
	int fast_link;
	int p;
	llint w;
};

int n, q;
V g[N];
int tin[N];
int tout[N];
int t;
map<pii, int> ribs_id;
map<pii, llint> ribs_w;
int id_to_v[N];
vi cur;

void dfs1(int v, int p) {
	if (p != -1) {
		id_to_v[ribs_id[pii{p, v}]] = v;
		g[v].p = p;
		g[v].w = ribs_w[pii{p, v}];
	}
	tin[v] = t++;

	cur.push_back(v);
	int id = max(0, SZ(cur) - 450);
	g[v].up450 = cur[id];

	for (Rib r: g[v].next) if (r.to != p)
		dfs1(r.to, v);

	cur.pop_back();

	tout[v] = t++;
}

void dfs2(int v, int p) {

	if (p != -1) {
		if (g[v].w == 1) {
			g[v].fast_link = g[p].fast_link;
		} else {
			g[v].fast_link = v;
		}
	} else {
		g[v].fast_link = 0;
	}
	for (Rib r: g[v].next) if (r.to != p)
		dfs2(r.to, v);
}

inline bool is_upper(int a, int b) {
	return tin[a] < tin[b]  && tin[b] < tout[a] &&
				 tin[a] < tout[b] && tout[b] < tout[a];
}

int lca(int a, int b) {
	if (is_upper(a, b)) return a;
	if (is_upper(b, a)) return b;
	while (!is_upper(g[a].up450, b))
		a = g[a].up450;
	while (g[a].p != -1 && !is_upper(g[a].p, b))
		a = g[a].p;
	return g[a].p;
}

int find(int v) {
	if (v == 0)
		return 0;
	if (g[v].w > 1)
		return v;
	return g[v].fast_link = find(g[v].fast_link == v ? g[v].p : g[v].fast_link);
}

void go1(int a, int c, llint &w) {
	while (w > 0) {
		if (!is_upper(c, a))
			return;
		if (g[a].w != 1) {
			w /= g[a].w;
			a = g[a].p;
		} else {
			a = find(a);
		}
	}
}

void go2(int b, int c, llint &w) {
	if (!is_upper(c, b))
		return;
	if (w == 0)
		return;
	vi v;
	{
		int a = b;
		while (is_upper(g[b].up450, a)) {
			if (g[a].w != 1) {
				v.push_back(g[a].w);
				a = g[a].p;
			} else {
				a = find(a);
			}
		}
	}
	for (int i = SZ(v) - 1; i >= 0 && w > 1; --i) {
		w /= v[i];
	}
}

void solve(int a, int b, int c, llint &w) {
	if (w == 0)
		return;
	go1(a, c, w);
	go2(b, c, w);
}

void change(int id, llint c) {
	int v = id_to_v[id];
	g[v].w = c;
}

void task() {
	scanf("%d %d", &n, &q);
	for (int i = 0; i < n - 1; ++i) {
		int a, b;
		llint w;
		scanf("%d %d %I64d", &a, &b, &w);
		--a, --b;
		ribs_id[pii{a,b}] = i;
		ribs_id[pii{b,a}] = i;
		ribs_w[pii{a, b}] = w;
		ribs_w[pii{b, a}] = w;
		g[a].next.push_back(Rib{b, w});
		g[b].next.push_back(Rib{a, w});
	}
	dfs1(0, -1);
	dfs2(0, -1);

//	dbg(is_upper())

	while (q--) {
		int cmd;
		scanf("%d", &cmd);
		if (cmd == 1) {
			int a, b;
			llint w;
			scanf("%d %d %I64d", &a, &b, &w);
			--a, --b;
			if (a == b) {
				printf("%I64d\n", w);
				continue;
			}
			int c = lca(a, b);
			solve(a, b, c, w);
			printf("%I64d\n", w);
		} else if (cmd == 2) {
			int p;
			llint c;
			scanf("%d %I64d", &p, &c);
			--p;
			change(p, c);
		}
	}
}


// Smile please :)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cassert>
#include <cctype>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <string>
#include <iomanip>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
#include <list>
#include <bitset>
#include <climits>
//#include <unordered_map>
//#include <unordered_set>
using namespace std;

//#undef KVARK_DEBUG

#ifdef KVARK_DEBUG
	#include "../h/debug.h"
#else
#define dbg(...) (void(1));
#define dbg2(...) (void(1));
#define dbg3(...) (void(1));
#define dbg4(...) (void(1));
#define dbg5(...) (void(1));
#define dbgp(...) (void(1));
#define dbg_arr(...) (void(1));
#define dbg_vec(...) (void(1));
#endif

typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef pair<double, int> pdi;
typedef vector<int> vi;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<vector<int> > vvi;
typedef vector<vector<pii> > vvpii;
typedef vector<vector<long long> > vvl;
typedef vector<long long> vl;
typedef long long int llint;

#define ALL(v) (v.begin()), (v.end())
#define SZ(v) ((int)((v).size()))
#define endl "\n"

void task();

int main(){
#ifdef KVARK
	freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	srand(time(0));
#endif
//	ios_base::sync_with_stdio(0);

	task();

#ifdef KVARK_DEBUG
	my_debug::printProcessInfo();
#endif
	return 0;
}
const int INF = 0x3f3f3f3f;
const int N = 2e5+10;
const int M = 2e5+10;

struct Rib {
	int to;
	llint w;
};

struct V {
	vector<Rib> next;
	int up450;
	int up600;
	int up200;
	int fast_link;
	int p;
	llint w;
};

int n, q;
V g[N];
int tin[N];
int tout[N];
int t;
map<pii, int> ribs_id;
map<pii, llint> ribs_w;
int id_to_v[N];
vi cur;

void dfs1(int v, int p) {
	if (p != -1) {
		id_to_v[ribs_id[pii{p, v}]] = v;
		g[v].p = p;
		g[v].w = ribs_w[pii{p, v}];
	}
	tin[v] = t++;

	cur.push_back(v);
	int id = max(0, SZ(cur) - 450);
	g[v].up450 = cur[id];
	id = max(0, SZ(cur) - 200);
	g[v].up200 = cur[id];
	id = max(0, SZ(cur) - 600);
	g[v].up600 = cur[id];
	g[v].fast_link = v;

	for (Rib r: g[v].next) if (r.to != p)
		dfs1(r.to, v);

	cur.pop_back();

	tout[v] = t++;
}

inline bool is_upper(int a, int b) {
	return tin[a] < tin[b]  && tin[b] < tout[a] &&
				 tin[a] < tout[b] && tout[b] < tout[a];
}

int lca(int a, int b) {
	if (is_upper(a, b)) return a;
	if (is_upper(b, a)) return b;
	while (!is_upper(g[a].up450, b))
		a = g[a].up450;
	while (g[a].p != -1 && !is_upper(g[a].p, b))
		a = g[a].p;
	return g[a].p;
}

int find(int v) {
	if (v == 0)
		return 0;
	if (g[v].w > 1)
		return v;
	return g[v].fast_link = find(g[v].fast_link == v ? g[v].p : g[v].fast_link);
}

void go1(int a, int c, llint &w) {
	while (w > 0 && is_upper(c, a)) {
		if (g[a].w != 1) {
			w /= g[a].w;
			a = g[a].p;
		} else {
			a = find(a);
		}
	}
}

void go450(int b, int c, llint &w) {
	if (!is_upper(c, b))
		return;
	go450(g[b].up450, c, w);
	if (w == 0)
		return;
	vi v;
	{
		int a = b;
		while (is_upper(g[b].up450, a)) {
			if (g[a].w != 1) {
				v.push_back(g[a].w);
				a = g[a].p;
			} else {
				a = find(a);
			}
		}
	}
	for (int i = SZ(v) - 1; i >= 0 && w > 0; --i) {
		w /= v[i];
	}
}

void go200(int b, int c, llint &w) {
	if (!is_upper(c, b))
		return;
	go200(g[b].up200, c, w);
	if (w == 0)
		return;
	vi v;
	{
		int a = b;
		while (is_upper(g[b].up200, a)) {
			if (g[a].w != 1) {
				v.push_back(g[a].w);
				a = g[a].p;
			} else {
				a = find(a);
			}
		}
	}
	for (int i = SZ(v) - 1; i >= 0 && w > 0; --i) {
		w /= v[i];
	}
}

void go600(int b, int c, llint &w) {
	if (!is_upper(c, b))
		return;
	go600(g[b].up600, c, w);
	if (w == 0)
		return;
	vi v;
	{
		int a = b;
		while (is_upper(g[b].up600, a)) {
			if (g[a].w != 1) {
				v.push_back(g[a].w);
				a = g[a].p;
			} else {
				a = find(a);
			}
		}
	}
	for (int i = SZ(v) - 1; i >= 0 && w > 0; --i) {
		w /= v[i];
	}
}

void go2(int b, int c, llint &w) {
	int r = rand()%3;
	if (r == 0)
		go200(b, c, w);
	if (r == 1)
		go450(b, c, w);
	if (r == 2)
		go600(b, c, w);
}

void solve(int a, int b, int c, llint &w) {
	if (w == 0)
		return;
	go1(a, c, w);
	go2(b, c, w);
}

void change(int id, llint c) {
	int v = id_to_v[id];
	g[v].w = c;
}

map<pii, llint> ans;

void task() {
	scanf("%d %d", &n, &q);
	for (int i = 0; i < n - 1; ++i) {
		int a, b;
		llint w;
		scanf("%d %d %I64d", &a, &b, &w);
		--a, --b;
		ribs_id[pii{a,b}] = i;
		ribs_id[pii{b,a}] = i;
		ribs_w[pii{a, b}] = w;
		ribs_w[pii{b, a}] = w;
		g[a].next.push_back(Rib{b, w});
		g[b].next.push_back(Rib{a, w});
	}
	dfs1(0, -1);

//	dbg(is_upper())

	while (q--) {
		int cmd;
		scanf("%d", &cmd);
		if (cmd == 1) {
			int a, b;
			llint w;
			scanf("%d %d %I64d", &a, &b, &w);
			--a, --b;
			if (a == b) {
				printf("%I64d\n", w);
				continue;
			}
			if (ans.count(pii{a, b})) {
				printf("%I64d\n", ans[pii{a, b}]);
				continue;
			}
			int c = lca(a, b);
			solve(a, b, c, w);
			printf("%I64d\n", w);
		} else if (cmd == 2) {
			int p;
			llint c;
			scanf("%d %I64d", &p, &c);
			--p;
			change(p, c);
			ans.clear();
		}
	}
}


#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 1000000000000000000
#define Mn 200005
#define Mm 600005
#define mod 10000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int read() {
    char c;
    int ans=0,f=1;c=getchar();
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') {ans=ans*10+c-'0';c=getchar();}
    return  ans*f;
}
struct edge {
    int v,next,id;
    ll w;
}e[Mm<<1];
int tot,head[Mn],M;
int dep[Mn],pre[Mn],siz[Mn],top[Mn],id[Mn],son[Mn],len;
ll val[Mn];
ll q[Mm];
int hs[Mn];
inline void addedge(int u,int v,ll w,int id) {
    e[tot].v=v;
    e[tot].w=w;
    e[tot].id=id;
    e[tot].next=head[u];
    head[u]=tot++;
}
inline void dfs(int u,int fa,int d) {
    int v;siz[u]=1;pre[u]=fa;dep[u]=d;
    for(int i=head[u];~i;i=e[i].next) {
        v=e[i].v;
        if(v==fa) continue;
        val[v]=e[i].w;
        hs[e[i].id]=v;
        dfs(v,u,d+1);
        siz[u]+=siz[v];
        if(son[u]==-1||siz[v]>siz[son[u]])
            son[u]=v;
    }
}
inline void DFS(int u,int tp) {
    top[u]=tp;
    id[u]=++len;
    if(son[u]==-1) return ;
    DFS(son[u],tp);int v;
    for(int i=head[u];~i;i=e[i].next) {
        v=e[i].v;
        if(v!=son[u]&&v!=pre[u]) DFS(v,v);
    }
}
ll sum;
inline ll add(ll a,ll b) {
    if(a==0||b==0||INF/b<a) return 0;
    return b*a;
}
inline void up(int u) {
    q[u]=add(q[ul],q[ur]);
}
inline void build(int n) {
    for(int i=1;i<=n;i++) q[id[i]+M]=val[i];
    for(int u=M-1;u>0;u--) up(u);
}
inline void updata(int u,ll v) {
    for(q[u+=M]=v,u>>=1; u; u>>=1) up(u);
}
inline void query(int s,int t)  {
    for(s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1) {
        if(~s&1) sum=add(q[s^1],sum);
        if(t&1) sum=add(q[t^1],sum);
        if(sum==0) return;
    }
}
inline void answer(int x,int y) {
    sum=1;
    while(top[x]!=top[y]) {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        query(id[top[x]],id[x]);
        if(sum==0) return;
        x=pre[top[x]];
    }
    if(x==y) return;
    if(dep[x]>dep[y]) swap(x,y);
    query(id[x]+1,id[y]);
}
void init() {
    tot=0;len=0;
    CLR(head,-1);
    CLR(son,-1);
}
int main() {
    int n=read(),m=read();
    int u,v;init();int st;ll w;
    u=read();v=read();st=u;
    scanf("%I64d",&w);
    addedge(u,v,w,1);
    addedge(v,u,w,1);
    for(int i=2;i<n;i++) {
        u=read();v=read();
        scanf("%I64d",&w);
        addedge(u,v,w,i);
        addedge(v,u,w,i);
    }
    val[st]=1;
    for(M=1;M<=n+1;M<<=1);
    dfs(st,0,0);
    DFS(st,st);
    build(n);
    while(m--) {
        int k=read();
        if(k==1) {
            u=read();v=read();
            ll s;scanf("%I64d",&s);
            answer(u,v);
            if(sum==0) printf("0\n");
            else printf("%I64d\n",s/sum);
        }else {
            int u=read();scanf("%I64d",&w);
            updata(id[hs[u]],w);
        }
    }
    return 0;
}


#include <bits/stdc++.h>

#define debug(x) cout << #x << " = " << x << endl
#define fori(i, ini, lim) for(int i = int(ini); i < int(lim); i++)
#define ford(i, ini, lim) for(int i = int(ini); i >= int(lim); i--)

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;

const int MAX = 1e5 + 5;
constexpr int SQRT_MAX = sqrt(MAX) + 20;
vector<int> adj[MAX], guys[MAX];
bool visited[MAX];
double ans[SQRT_MAX + 20][SQRT_MAX + 20];
ll pre[SQRT_MAX + 20][MAX];
int pset[MAX], size[MAX], dte[MAX], dis[MAX], idx[MAX], back[MAX], diameter[MAX];
int n, m, Q;

int find_set(int i) {
	return pset[i] == i ? i : pset[i] = find_set(pset[i]);
}

inline void union_sets(int i, int j) {
	size[find_set(j)] += size[find_set(i)];
	pset[find_set(i)] = find_set(j);
}

inline bool same_set(int i, int j) {
	return find_set(i) == find_set(j);
}

int bfs(int source) {
	memset(visited, false, sizeof visited);
	queue<int> q;
	q.push(source);
	visited[source] = true;
	int last = -1;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		last = cur;
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				visited[each] = true;
			}
		}
	}
	return last;
}

int bfs2(int source) {
	queue<int> q;
	q.push(source);
	memset(visited, false, sizeof visited);
	visited[source] = true;
	dis[source] = 0;
	int max_dis = 0;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		dte[cur] = max(dte[cur], dis[cur]);
		max_dis = max(max_dis, dis[cur]);
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				dis[each] = dis[cur] + 1;
				visited[each] = true;
			}
		}
	}
	return max_dis;
}

void calc(int cur_set) {
	if(size[cur_set] == 1) {
		dte[cur_set] = 0;
		return;
	}
	int one_edge = bfs(cur_set);
	int other_edge = bfs(one_edge);
	diameter[cur_set] = max(bfs2(one_edge), bfs2(other_edge));
}

ll tmp[SQRT_MAX + 20];

double roll(int pu, int pv) {
	int N = size[pu];
	int M = size[pv];
	int D = max(diameter[pu], diameter[pv]) - 1;
	double total = 0.0;
	ll *ptr;
	if(pv >= SQRT_MAX) {
		ptr = pre[idx[pv]];
	}
	else {
		memset(tmp, 0, sizeof tmp);
		ford(i, guys[pv].size() - 1, 0) {
			tmp[i] = tmp[i + 1] + guys[pv][i];
		}
		ptr = tmp;
	}
	for(auto &each : guys[pu]) {
		int pos = upper_bound(guys[pv].begin(), guys[pv].end(), D - each) - guys[pv].begin();
		int cur = M - pos;
		total += 1LL * cur * each;
		total += cur;
		total += ptr[pos];
		total += 1LL * pos * (D + 1);
	}
	return total / (1LL * N * M);
}

int main() {
	scanf("%d %d %d", &n, &m, &Q);

	fori(i, 1, n + 1) {
		pset[i] = i;
		size[i] = 1;
	}

	fori(i, 0, m) {
		int u, v;
		scanf("%d %d", &u, &v);
		if(!same_set(u, v)) {
			union_sets(u, v);
		}
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	set<int> sets;
	fori(i, 1, n + 1) {
		sets.insert(find_set(i));
	}

	memset(dte, 0, sizeof dte);
	for(auto &each : sets) {
		calc(each);
	}

	fori(i, 1, n + 1) {
		guys[find_set(i)].push_back(dte[i]);
	}
	for(auto &each : sets) {
		sort(guys[each].begin(), guys[each].end());
	}

	vector<int> big;
	for(auto &each : sets) {
		if(size[each] >= SQRT_MAX) {
			idx[each] = big.size();
			back[big.size()] = each;
			big.push_back(each);
			ford(i, guys[each].size() - 1, 0) {
				pre[idx[each]][i] += pre[idx[each]][i + 1] + guys[each][i];
			}
		}
	}

	fori(i, 0, big.size()) {
		fori(j, i + 1, big.size()) {
			int pu = big[i];
			int pv = big[j];
			if(size[pu] > size[pv]) {
				swap(pu, pv);
			}
			ans[idx[pu]][idx[pv]] = roll(pu, pv);
		}
	}

	fori(t, 0, Q) {
		int u, v;
		scanf("%d %d", &u, &v);
		int pu = find_set(u);
		int pv = find_set(v);
		// pu should be smaller
		if(size[pu] > size[pv]) {
			swap(pu, pv);
		}
		if(pu == pv) {
			puts("-1");
		}
		else if(size[pu] >= SQRT_MAX && size[pv] >= SQRT_MAX) {
			cout << "OI" << endl;
			printf("%.15lf\n", ans[idx[pu]][idx[pv]]);
		}
		else {
			double nois = roll(pu, pv);
			printf("%.15lf\n", nois);
		}
	}

	return 0;
}


#include <bits/stdc++.h>

#define debug(x) cout << #x << " = " << x << endl
#define fori(i, ini, lim) for(int i = int(ini); i < int(lim); i++)
#define ford(i, ini, lim) for(int i = int(ini); i >= int(lim); i--)

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;

const int MAX = 1e5 + 2;
constexpr int BLOCK_SIZE = sqrt(MAX) + 80;
constexpr int BLOCKS = MAX / BLOCK_SIZE + 5;
vector<int> adj[MAX], guys[MAX];
bool visited[MAX];
double ans[BLOCKS][BLOCKS];
ll pre[BLOCKS][MAX];
int pset[MAX], size[MAX], dte[MAX], dis[MAX], idx[MAX], back[MAX], diameter[MAX];
int n, m, Q;

int find_set(int i) {
	return pset[i] == i ? i : pset[i] = find_set(pset[i]);
}

inline void union_sets(int i, int j) {
	size[find_set(j)] += size[find_set(i)];
	pset[find_set(i)] = find_set(j);
}

inline bool same_set(int i, int j) {
	return find_set(i) == find_set(j);
}

int bfs(int source) {
	memset(visited, false, sizeof visited);
	queue<int> q;
	q.push(source);
	visited[source] = true;
	int last = -1;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		last = cur;
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				visited[each] = true;
			}
		}
	}
	return last;
}

int bfs2(int source) {
	queue<int> q;
	q.push(source);
	memset(visited, false, sizeof visited);
	visited[source] = true;
	dis[source] = 0;
	int max_dis = 0;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		dte[cur] = max(dte[cur], dis[cur]);
		max_dis = max(max_dis, dis[cur]);
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				dis[each] = dis[cur] + 1;
				visited[each] = true;
			}
		}
	}
	return max_dis;
}

void calc(int cur_set) {
	if(size[cur_set] == 1) {
		dte[cur_set] = 0;
		return;
	}
	int one_edge = bfs(cur_set);
	int other_edge = bfs(one_edge);
	diameter[cur_set] = max(bfs2(one_edge), bfs2(other_edge));
}

ll tmp[BLOCK_SIZE];

double roll(int pu, int pv) {
	int N = size[pu];
	int M = size[pv];
	int D = max(diameter[pu], diameter[pv]) - 1;
	double total = 0.0;
	ll *ptr;
	if(size[pv] >= BLOCK_SIZE) {
		ptr = pre[idx[pv]];
	}
	else {
		memset(tmp, 0, sizeof tmp);
		ford(i, guys[pv].size() - 1, 0) {
			tmp[i] = tmp[i + 1] + guys[pv][i];
		}
		ptr = tmp;
	}
	for(auto &each : guys[pu]) {
		int pos = upper_bound(guys[pv].begin(), guys[pv].end(), D - each) - guys[pv].begin();
		int cur = M - pos;
		total += 1LL * cur * each;
		total += cur;
		total += ptr[pos];
		total += 1LL * pos * (D + 1);
	}
	return total / (1LL * N * M);
}

int main() {
	scanf("%d %d %d", &n, &m, &Q);

	fori(i, 1, n + 1) {
		pset[i] = i;
		size[i] = 1;
	}

	fori(i, 0, m) {
		int u, v;
		scanf("%d %d", &u, &v);
		if(!same_set(u, v)) {
			union_sets(u, v);
		}
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	set<int> sets;
	fori(i, 1, n + 1) {
		sets.insert(find_set(i));
	}

	memset(dte, 0, sizeof dte);
	for(auto &each : sets) {
		calc(each);
	}

	fori(i, 1, n + 1) {
		guys[find_set(i)].push_back(dte[i]);
	}
	for(auto &each : sets) {
		sort(guys[each].begin(), guys[each].end());
	}

	vector<int> big;
	for(auto &each : sets) {
		if(size[each] >= BLOCK_SIZE) {
			idx[each] = big.size();
			back[big.size()] = each;
			big.push_back(each);
			ford(i, guys[each].size() - 1, 0) {
				pre[idx[each]][i] = pre[idx[each]][i + 1] + guys[each][i];
			}
		}
	}

	fori(i, 0, big.size()) {
		fori(j, i + 1, big.size()) {
			int pu = big[i];
			int pv = big[j];
			if(size[pu] > size[pv]) {
				swap(pu, pv);
			}
			ans[idx[pv]][idx[pu]] = ans[idx[pu]][idx[pv]] = roll(pu, pv);
		}
	}

	fori(t, 0, Q) {
		int u, v;
		scanf("%d %d", &u, &v);
		int pu = find_set(u);
		int pv = find_set(v);
		// pu should be smaller
		if(size[pu] > size[pv]) {
			swap(pu, pv);
		}
		if(pu == pv) {
			puts("-1");
		}
		else if(size[pu] >= BLOCK_SIZE && size[pv] >= BLOCK_SIZE) {
			printf("%.15lf\n", ans[idx[pu]][idx[pv]]);
		}
		else {
			double nois = roll(pu, pv);
			printf("%.15lf\n", nois);
		}
	}

	return 0;
}


#include <bits/stdc++.h>

#define debug(x) cout << #x << " = " << x << endl
#define fori(i, ini, lim) for(int i = int(ini); i < int(lim); i++)
#define ford(i, ini, lim) for(int i = int(ini); i >= int(lim); i--)

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;

const int MAX = 1e5 + 2;
constexpr int SQRT_MAX = sqrt(MAX) + 1;
vector<int> adj[MAX], guys[MAX];
bool visited[MAX];
double ans[SQRT_MAX + 1][SQRT_MAX + 1];
ll pre[SQRT_MAX + 1][MAX];
int pset[MAX], size[MAX], dte[MAX], dis[MAX], idx[MAX], back[MAX], diameter[MAX];
int n, m, Q;

int find_set(int i) {
	return pset[i] == i ? i : pset[i] = find_set(pset[i]);
}

inline void union_sets(int i, int j) {
	size[find_set(j)] += size[find_set(i)];
	pset[find_set(i)] = find_set(j);
}

inline bool same_set(int i, int j) {
	return find_set(i) == find_set(j);
}

int bfs(int source) {
	memset(visited, false, sizeof visited);
	queue<int> q;
	q.push(source);
	visited[source] = true;
	int last = -1;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		last = cur;
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				visited[each] = true;
			}
		}
	}
	return last;
}

int bfs2(int source) {
	queue<int> q;
	q.push(source);
	memset(visited, false, sizeof visited);
	visited[source] = true;
	dis[source] = 0;
	int max_dis = 0;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		dte[cur] = max(dte[cur], dis[cur]);
		max_dis = max(max_dis, dis[cur]);
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				dis[each] = dis[cur] + 1;
				visited[each] = true;
			}
		}
	}
	return max_dis;
}

void calc(int cur_set) {
	if(size[cur_set] == 1) {
		dte[cur_set] = 0;
		return;
	}
	int one_edge = bfs(cur_set);
	int other_edge = bfs(one_edge);
	diameter[cur_set] = max(bfs2(one_edge), bfs2(other_edge));
}

ll tmp[SQRT_MAX + 20];

double roll(int pu, int pv) {
	int N = size[pu];
	int M = size[pv];
	int D = max(diameter[pu], diameter[pv]) - 1;
	double total = 0.0;
	ll *ptr;
	if(pv >= SQRT_MAX) {
		ptr = pre[idx[pv]];
	}
	else {
		memset(tmp, 0, sizeof tmp);
		ford(i, guys[pv].size() - 1, 0) {
			tmp[i] = tmp[i + 1] + guys[pv][i];
		}
		ptr = tmp;
	}
	for(auto &each : guys[pu]) {
		int pos = upper_bound(guys[pv].begin(), guys[pv].end(), D - each) - guys[pv].begin();
		int cur = M - pos;
		total += 1LL * cur * each;
		total += cur;
		total += ptr[pos];
		total += 1LL * pos * (D + 1);
	}
	return total / (1LL * N * M);
}

int main() {
	scanf("%d %d %d", &n, &m, &Q);

	fori(i, 1, n + 1) {
		pset[i] = i;
		size[i] = 1;
	}

	fori(i, 0, m) {
		int u, v;
		scanf("%d %d", &u, &v);
		if(!same_set(u, v)) {
			union_sets(u, v);
		}
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	set<int> sets;
	fori(i, 1, n + 1) {
		sets.insert(find_set(i));
	}

	memset(dte, 0, sizeof dte);
	for(auto &each : sets) {
		calc(each);
	}

	fori(i, 1, n + 1) {
		guys[find_set(i)].push_back(dte[i]);
	}
	for(auto &each : sets) {
		sort(guys[each].begin(), guys[each].end());
	}

	vector<int> big;
	for(auto &each : sets) {
		if(size[each] >= SQRT_MAX) {
			idx[each] = big.size();
			back[big.size()] = each;
			big.push_back(each);
			ford(i, guys[each].size() - 1, 0) {
				pre[idx[each]][i] += pre[idx[each]][i + 1] + guys[each][i];
			}
		}
	}

	fori(i, 0, big.size()) {
		fori(j, i + 1, big.size()) {
			int pu = big[i];
			int pv = big[j];
			if(size[pu] > size[pv]) {
				swap(pu, pv);
			}
			ans[idx[pu]][idx[pv]] = roll(pu, pv);
		}
	}

	fori(t, 0, Q) {
		int u, v;
		scanf("%d %d", &u, &v);
		int pu = find_set(u);
		int pv = find_set(v);
		// pu should be smaller
		if(size[pu] > size[pv]) {
			swap(pu, pv);
		}
		if(pu == pv) {
			puts("-1");
		}
		else if(size[pu] >= SQRT_MAX && size[pv] >= SQRT_MAX) {
			cout << "OI" << endl;
			printf("%.15lf\n", ans[idx[pu]][idx[pv]]);
		}
		else {
			double nois = roll(pu, pv);
			printf("%.15lf\n", nois);
		}
	}

	return 0;
}


#include <bits/stdc++.h>

#define debug(x) cout << #x << " = " << x << endl
#define fori(i, ini, lim) for(int i = int(ini); i < int(lim); i++)
#define ford(i, ini, lim) for(int i = int(ini); i >= int(lim); i--)

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;

const int MAX = 1e5 + 2;
constexpr int BLOCK_SIZE = sqrt(MAX) + 80;
constexpr int BLOCKS = MAX / BLOCK_SIZE + 5;
vector<int> adj[MAX], guys[MAX];
bool visited[MAX];
double ans[BLOCKS][BLOCKS];
ll pre[BLOCKS][MAX];
int pset[MAX], size[MAX], dte[MAX], dis[MAX], idx[MAX], back[MAX], diameter[MAX];
int n, m, Q;

int find_set(int i) {
	return pset[i] == i ? i : pset[i] = find_set(pset[i]);
}

inline void union_sets(int i, int j) {
	size[find_set(j)] += size[find_set(i)];
	pset[find_set(i)] = find_set(j);
}

inline bool same_set(int i, int j) {
	return find_set(i) == find_set(j);
}

int bfs(int source) {
	memset(visited, false, sizeof visited);
	queue<int> q;
	q.push(source);
	visited[source] = true;
	int last = -1;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		last = cur;
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				visited[each] = true;
			}
		}
	}
	return last;
}

int bfs2(int source) {
	queue<int> q;
	q.push(source);
	memset(visited, false, sizeof visited);
	visited[source] = true;
	dis[source] = 0;
	int max_dis = 0;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		dte[cur] = max(dte[cur], dis[cur]);
		max_dis = max(max_dis, dis[cur]);
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				dis[each] = dis[cur] + 1;
				visited[each] = true;
			}
		}
	}
	return max_dis;
}

void calc(int cur_set) {
	if(size[cur_set] == 1) {
		dte[cur_set] = 0;
		return;
	}
	int one_edge = bfs(cur_set);
	int other_edge = bfs(one_edge);
	diameter[cur_set] = max(bfs2(one_edge), bfs2(other_edge));
}

ll tmp[BLOCK_SIZE];

double roll(int pu, int pv) {
	int N = size[pu];
	int M = size[pv];
	int D = max(diameter[pu], diameter[pv]) - 1;
	double total = 0.0;
	ll *ptr;
	if(pv >= BLOCK_SIZE) {
		ptr = pre[idx[pv]];
	}
	else {
		memset(tmp, 0, sizeof tmp);
		ford(i, guys[pv].size() - 1, 0) {
			tmp[i] = tmp[i + 1] + guys[pv][i];
		}
		ptr = tmp;
	}
	for(auto &each : guys[pu]) {
		int pos = upper_bound(guys[pv].begin(), guys[pv].end(), D - each) - guys[pv].begin();
		int cur = M - pos;
		total += 1LL * cur * each;
		total += cur;
		total += ptr[pos];
		total += 1LL * pos * (D + 1);
	}
	return total / (1LL * N * M);
}

int main() {
	scanf("%d %d %d", &n, &m, &Q);

	fori(i, 1, n + 1) {
		pset[i] = i;
		size[i] = 1;
	}

	fori(i, 0, m) {
		int u, v;
		scanf("%d %d", &u, &v);
		if(!same_set(u, v)) {
			union_sets(u, v);
		}
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	set<int> sets;
	fori(i, 1, n + 1) {
		sets.insert(find_set(i));
	}

	memset(dte, 0, sizeof dte);
	for(auto &each : sets) {
		calc(each);
	}

	fori(i, 1, n + 1) {
		guys[find_set(i)].push_back(dte[i]);
	}
	for(auto &each : sets) {
		sort(guys[each].begin(), guys[each].end());
	}

	vector<int> big;
	for(auto &each : sets) {
		if(size[each] >= BLOCK_SIZE) {
			idx[each] = big.size();
			back[big.size()] = each;
			big.push_back(each);
			ford(i, guys[each].size() - 1, 0) {
				pre[idx[each]][i] += pre[idx[each]][i + 1] + guys[each][i];
			}
		}
	}

	fori(i, 0, big.size()) {
		fori(j, i + 1, big.size()) {
			int pu = big[i];
			int pv = big[j];
			if(size[pu] > size[pv]) {
				swap(pu, pv);
			}
			ans[idx[pu]][idx[pv]] = roll(pu, pv);
		}
	}

	fori(t, 0, Q) {
		int u, v;
		scanf("%d %d", &u, &v);
		int pu = find_set(u);
		int pv = find_set(v);
		// pu should be smaller
		if(size[pu] > size[pv]) {
			swap(pu, pv);
		}
		if(pu == pv) {
			puts("-1");
		}
		else if(size[pu] >= BLOCK_SIZE && size[pv] >= BLOCK_SIZE) {
			cout << "OI" << endl;
			printf("%.15lf\n", ans[idx[pu]][idx[pv]]);
		}
		else {
			double nois = roll(pu, pv);
			printf("%.15lf\n", nois);
		}
	}

	return 0;
}


#include <bits/stdc++.h>

#define debug(x) cout << #x << " = " << x << endl
#define fori(i, ini, lim) for(int i = int(ini); i < int(lim); i++)
#define ford(i, ini, lim) for(int i = int(ini); i >= int(lim); i--)

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;

const int MAX = 1e5 + 2;
constexpr int BLOCK_SIZE = sqrt(MAX) + 80;
constexpr int BLOCKS = MAX / BLOCK_SIZE + 5;
vector<int> adj[MAX], guys[MAX];
bool visited[MAX];
double ans[BLOCKS][BLOCKS];
ll pre[BLOCKS][MAX];
int pset[MAX], size[MAX], dte[MAX], dis[MAX], idx[MAX], back[MAX], diameter[MAX];
int n, m, Q;

int find_set(int i) {
	return pset[i] == i ? i : pset[i] = find_set(pset[i]);
}

inline void union_sets(int i, int j) {
	size[find_set(j)] += size[find_set(i)];
	pset[find_set(i)] = find_set(j);
}

inline bool same_set(int i, int j) {
	return find_set(i) == find_set(j);
}

int bfs(int source) {
	memset(visited, false, sizeof visited);
	queue<int> q;
	q.push(source);
	visited[source] = true;
	int last = -1;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		last = cur;
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				visited[each] = true;
			}
		}
	}
	return last;
}

int bfs2(int source) {
	queue<int> q;
	q.push(source);
	memset(visited, false, sizeof visited);
	visited[source] = true;
	dis[source] = 0;
	int max_dis = 0;
	while(!q.empty()) {
		int cur = q.front(); q.pop();
		dte[cur] = max(dte[cur], dis[cur]);
		max_dis = max(max_dis, dis[cur]);
		for(auto &each : adj[cur]) {
			if(!visited[each]) {
				q.push(each);
				dis[each] = dis[cur] + 1;
				visited[each] = true;
			}
		}
	}
	return max_dis;
}

void calc(int cur_set) {
	if(size[cur_set] == 1) {
		dte[cur_set] = 0;
		return;
	}
	int one_edge = bfs(cur_set);
	int other_edge = bfs(one_edge);
	diameter[cur_set] = max(bfs2(one_edge), bfs2(other_edge));
}

ll tmp[BLOCK_SIZE];

double roll(int pu, int pv) {
	int N = size[pu];
	int M = size[pv];
	int D = max(diameter[pu], diameter[pv]) - 1;
	double total = 0.0;
	ll *ptr;
	if(pv >= BLOCK_SIZE) {
		ptr = pre[idx[pv]];
	}
	else {
		memset(tmp, 0, sizeof tmp);
		ford(i, guys[pv].size() - 1, 0) {
			tmp[i] = tmp[i + 1] + guys[pv][i];
		}
		ptr = tmp;
	}
	for(auto &each : guys[pu]) {
		int pos = upper_bound(guys[pv].begin(), guys[pv].end(), D - each) - guys[pv].begin();
		int cur = M - pos;
		total += 1LL * cur * each;
		total += cur;
		total += ptr[pos];
		total += 1LL * pos * (D + 1);
	}
	return total / (1LL * N * M);
}

int main() {
	scanf("%d %d %d", &n, &m, &Q);

	fori(i, 1, n + 1) {
		pset[i] = i;
		size[i] = 1;
	}

	fori(i, 0, m) {
		int u, v;
		scanf("%d %d", &u, &v);
		if(!same_set(u, v)) {
			union_sets(u, v);
		}
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	set<int> sets;
	fori(i, 1, n + 1) {
		sets.insert(find_set(i));
	}

	memset(dte, 0, sizeof dte);
	for(auto &each : sets) {
		calc(each);
	}

	fori(i, 1, n + 1) {
		guys[find_set(i)].push_back(dte[i]);
	}
	for(auto &each : sets) {
		sort(guys[each].begin(), guys[each].end());
	}

	vector<int> big;
	for(auto &each : sets) {
		if(size[each] >= BLOCK_SIZE) {
			idx[each] = big.size();
			back[big.size()] = each;
			big.push_back(each);
			ford(i, guys[each].size() - 1, 0) {
				pre[idx[each]][i] += pre[idx[each]][i + 1] + guys[each][i];
			}
		}
	}

	fori(i, 0, big.size()) {
		fori(j, i + 1, big.size()) {
			int pu = big[i];
			int pv = big[j];
			if(size[pu] > size[pv]) {
				swap(pu, pv);
			}
			ans[idx[pu]][idx[pv]] = roll(pu, pv);
		}
	}

	fori(t, 0, Q) {
		int u, v;
		scanf("%d %d", &u, &v);
		int pu = find_set(u);
		int pv = find_set(v);
		// pu should be smaller
		if(size[pu] > size[pv]) {
			swap(pu, pv);
		}
		if(pu == pv) {
			puts("-1");
		}
		else if(size[pu] >= BLOCK_SIZE && size[pv] >= BLOCK_SIZE) {
			printf("%.15lf\n", ans[idx[pu]][idx[pv]]);
		}
		else {
			double nois = roll(pu, pv);
			printf("%.15lf\n", nois);
		}
	}

	return 0;
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N],t[N];
int f[N],g[N],record[N],vis[N];
long long sum,ans;
vector<long long>A[N],B[N];
int n,m,Q,id,len,x,y,i,j,tot,u,v,flag,k;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int fa,int dis){
	vis[x]=1;
	if (flag==1) record[x]=dis;
	else if (flag==2) f[max(record[x],dis)]++;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa)
	    DFS(a[x][i],x,dis+1);
}
int main(){
	//freopen("d.in","r",stdin);
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;flag=0;DFS(i,0,0);x=id;
	  	id=0;len=-1;flag=1;DFS(x,0,0);y=id;
	  	id=0;len=-1;flag=2;DFS(y,0,0);
	  	x=get(i);

	  	for (k=0;k<=len;k++)
	  	  t[x].push_back(f[k]);

	  	for (sum=k=0;k<=len;k++)
			  sum+=f[k],A[x].push_back(sum);
	  	for (sum=0,k=len;k>=0;k--)
			  sum+=f[k],B[x].push_back(sum);
	  	for (k=0;k<=len;k++) f[k]=0;

	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		if (t[x].size()<t[y].size()) swap(x,y);
		n=t[x].size()-1;m=t[y].size()-1;
		//for (i=0;i<=n;i++) printf("%d ",t[x][i]);puts("");
		//for (i=0;i<=m;i++) printf("%d ",t[y][i]);puts("");
		u=n-1-m;ans=0;
		if (u>=0) ans+=1ll*A[x][u]*A[y][m]*n;
		++u;
		ans+=1ll*n*(1ll*m*(m+1)/2LL);

		for (i=u;i<=n;i++)
		  for (j=m-(u-i);j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*(i+j+1);
		/*u~n:
		  u    [m,m]
		  u+1  [m-1,m]
		  n    [0,m]
		*/

		printf("%.10f\n",ans*1./(1ll*A[x][u]*B[y][m]));
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N],t[N];
int f[N],g[N],record[N],vis[N];
long long sum,ans;
vector<long long>A[N],B[N];
int n,m,Q,id,len,x,y,i,j,tot,u,v,flag,k;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int fa,int dis){
	vis[x]=1;
	if (flag==1) record[x]=dis;
	else if (flag==2) f[max(record[x],dis)]++;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa)
	    DFS(a[x][i],x,dis+1);
}
int main(){
	//freopen("d.in","r",stdin);
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;flag=0;DFS(i,0,0);x=id;
	  	id=0;len=-1;flag=1;DFS(x,0,0);y=id;
	  	id=0;len=-1;flag=2;DFS(y,0,0);
	  	x=get(i);

	  	for (k=0;k<=len;k++)
	  	  t[x].push_back(f[k]);

	  	for (sum=k=0;k<=len;k++)
			  sum+=f[k],A[x].push_back(sum);
	  	for (sum=0,k=len;k>=0;k--)
			  sum+=f[k],B[x].push_back(sum);
	  	for (k=0;k<=len;k++) f[k]=0;

	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		if (t[x].size()<t[y].size()) swap(x,y);
		n=t[x].size()-1;m=t[y].size()-1;
		//for (i=0;i<=n;i++) printf("%d ",t[x][i]);puts("");
		//for (i=0;i<=m;i++) printf("%d ",t[y][i]);puts("");
		u=n-1-m;
		if (u>=0) ans+=1ll*A[x][u]*A[y][m]*n;
		++u;
		ans+=1ll*n*(1ll*m*(m+1)/2LL);

		for (i=u;i<=n;i++)
		  for (j=m-(u-i);j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*(i+j+1);
		/*u~n:
		  u    [m,m]
		  u+1  [m-1,m]
		  n    [0,m]
		*/

		printf("%.10f\n",ans*1./(1ll*A[x][u]*B[y][m]));
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N];
int f[N],size[N],g[N],vis[N],A[2][N];
long long sum[N],B[2][N];
int n,m,Q,id,len,x,y,i,tot,ans,X,Y,u,v;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int dis){
	vis[x]=1;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=f[x])
	    f[a[x][i]]=x,DFS(a[x][i],dis+1);
}
void BFS(int x,int fa){
	size[x]=1;sum[x]=0;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa){
	  	if (a[x][i]==0) continue;
	  	if (X==x&&Y==a[x][i]) continue;
	  	if (X==a[x][i]&&Y==x) continue;
	  	int y=a[x][i];
	  	BFS(y,x);
	  	size[x]+=size[y];
	  	sum[x]+=sum[y]+size[y];
	  }
}
int main(){
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;f[i]=0;DFS(i,0);x=id;
	  	id=0;len=-1;f[x]=0;DFS(x,0);y=id;
	  	++tot;
	  	for (x=len/2;x;x--,y=f[y]);
	  	a[tot].push_back(y);
	  	a[tot].push_back(f[y]);
	  	X=y;Y=f[y];
	  	BFS(tot,0);
	  	x=get(i);++len;
	  	A[0][x]=size[a[tot][0]];
			B[0][x]=sum[a[tot][0]]+1ll*(len/2)*A[0][x];
	  	A[1][x]=size[a[tot][1]];
			B[1][x]=sum[a[tot][1]]+1ll*(len==1?0:(len+1)/2)*A[1][x];
	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		ans=0;
		for (u=0;u<2;u++)
		  for (v=0;v<2;v++)
		    if (A[u][x]&&A[v][y])
				  ans+=1ll*B[u][x]*A[v][y]+1ll*B[v][y]*A[u][x];
		printf("%.10f\n",ans*1./(A[0][x]+A[1][x])/(A[0][y]+A[1][y])+1.);
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N];
int f[N],size[N],g[N],vis[N],A[2][N];
long long sum[N],B[2][N];
int n,m,Q,id,len,x,y,i,tot,ans,X,Y,u,v;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int dis){
	vis[x]=1;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=f[x])
	    f[a[x][i]]=x,DFS(a[x][i],dis+1);
}
void BFS(int x,int fa){
	size[x]=1;sum[x]=0;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa){
	  	if (a[x][i]==0) continue;
	  	if (X==x&&Y==a[x][i]) continue;
	  	if (X==a[x][i]&&Y==x) continue;
	  	int y=a[x][i];
	  	BFS(y,x);
	  	size[x]+=size[y];
	  	sum[x]+=sum[y]+size[y];
	  }
}
int main(){
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;f[i]=0;DFS(i,0);x=id;
	  	id=0;len=-1;f[x]=0;DFS(x,0);y=id;
	  	++tot;
	  	for (x=len/2;x;x--,y=f[y]);
	  	a[tot].push_back(y);
	  	a[tot].push_back(f[y]);
	  	X=y;Y=f[y];
	  	BFS(tot,0);
	  	x=get(i);++len;
	  	A[0][x]=size[a[tot][0]];
			B[0][x]=sum[a[tot][0]]+1ll*(len/2)*A[0][x];
	  	A[1][x]=size[a[tot][1]];
			B[1][x]=sum[a[tot][1]]+1ll*(len==1?0:(len+1)/2)*A[1][x];
	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		ans=0;
		for (u=0;u<2;u++)
		  for (v=0;v<2;v++)
		    if (A[u][x]&&A[v][y])
				  ans+=1ll*A[u][x]*A[v][y]+B[u][x]+B[v][y];
		printf("%.10f\n",ans*1./(A[0][x]+A[1][x])/(A[0][y]+A[1][y]));
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N],t[N];
int f[N],g[N],record[N],vis[N];
long long sum,ans;
vector<long long>A[N],B[N];
int n,m,Q,id,len,x,y,i,j,tot,u,v,flag,k;
map<pair<int,int>,double>Hash;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int fa,int dis){
	vis[x]=1;
	if (flag==1) record[x]=dis;
	else if (flag==2) f[max(record[x],dis)]++;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa)
	    DFS(a[x][i],x,dis+1);
}
int main(){
	//freopen("d.in","r",stdin);
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;flag=0;DFS(i,0,0);x=id;
	  	id=0;len=-1;flag=1;DFS(x,0,0);y=id;
	  	id=0;len=-1;flag=2;DFS(y,0,0);
	  	x=get(i);

	  	for (k=0;k<=len;k++)
	  	  t[x].push_back(f[k]);

	  	for (sum=k=0;k<=len;k++)
			  sum+=f[k],A[x].push_back(sum);
	  	for (sum=k=0;k<=len;k++)
			  sum+=1ll*f[k]*k,B[x].push_back(sum);
	  	for (k=0;k<=len;k++) f[k]=0;

	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		if (t[x].size()<t[y].size()) swap(x,y);
		n=t[x].size()-1;m=t[y].size()-1;
		//for (i=0;i<=n;i++) printf("%d ",t[x][i]);puts("");
		//for (i=0;i<=m;i++) printf("%d ",t[y][i]);puts("");
		/*u=n-1-m;ans=0;
		if (u>=0) ans+=1ll*A[x][u]*A[y][m]*n;
		++u;
		ans+=1ll*n*(1ll*m*(m+1)/2LL);

		for (i=u;i<=n;i++)
		  for (j=m-(i-u);j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*(i+j+1);*/
		if (Hash.find(make_pair(x,y))!=Hash.end()){
			printf("%.10f\n",Hash[make_pair(x,y)]);
			continue;
		}
		ans=0;

		/*for (i=0;i<=n;i++)
		  for (j=0;j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*max(n,i+j+1);*/

		for (j=0;j<=m;j++){
			u=n-1-j;
			if (u>=0) ans+=1ll*t[y][j]*A[x][u]*n;
			ans+=1ll*t[y][j]*((B[x][n]-B[x][u])+1ll*(j+1)*(A[x][n]-A[x][u]));
		}
		/*u~n:
		  u    [m,m]
		  u+1  [m-1,m]
		  n    [0,m]
		*/
		//printf("%d %d\n",A[x][n],A[y][m]);
		printf("%.10f\n",Hash[make_pair(x,y)]=ans*1./(1ll*A[x][n]*A[y][m]));
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N],t[N];
int f[N],g[N],record[N],vis[N];
long long sum,ans;
vector<long long>A[N],B[N];
int n,m,Q,id,len,x,y,i,j,tot,u,v,flag,k;
map<pair<int,int>,double>Hash;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int fa,int dis){
	vis[x]=1;
	if (flag==1) record[x]=dis;
	else if (flag==2) f[max(record[x],dis)]++;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa)
	    DFS(a[x][i],x,dis+1);
}
int main(){
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;flag=0;DFS(i,0,0);x=id;
	  	id=0;len=-1;flag=1;DFS(x,0,0);y=id;
	  	id=0;len=-1;flag=2;DFS(y,0,0);
	  	x=get(i);

	  	for (k=0;k<=len;k++)
	  	  t[x].push_back(f[k]);

	  	for (sum=k=0;k<=len;k++)
			  sum+=f[k],A[x].push_back(sum);
	  	for (sum=k=0;k<=len;k++)
			  sum+=1ll*f[k]*k,B[x].push_back(sum);
	  	for (k=0;k<=len;k++) f[k]=0;

	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		if (t[x].size()<t[y].size()) swap(x,y);
		n=t[x].size()-1;m=t[y].size()-1;
		//for (i=0;i<=n;i++) printf("%d ",t[x][i]);puts("");
		//for (i=0;i<=m;i++) printf("%d ",t[y][i]);puts("");
		/*u=n-1-m;ans=0;
		if (u>=0) ans+=1ll*A[x][u]*A[y][m]*n;
		++u;
		ans+=1ll*n*(1ll*m*(m+1)/2LL);

		for (i=u;i<=n;i++)
		  for (j=m-(i-u);j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*(i+j+1);*/
		if (Hash.find(make_pair(x,y))!=Hash.end()){
			printf("%.10f\n",Hash[make_pair(x,y)]);
			continue;
		}
		ans=0;

		/*for (i=0;i<=n;i++)
		  for (j=0;j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*max(n,i+j+1);*/

		for (j=0;j<=m;j++){
			u=n-1-j;
			if (u>=0) ans+=1ll*t[y][j]*A[x][u]*n;
			ans+=1ll*t[y][j]*((B[x][n]-(u>=0?B[x][u]:0))+1ll*(j+1)*(A[x][n]-(u>=0?A[x][u]:0)));
		}
		/*u~n:
		  u    [m,m]
		  u+1  [m-1,m]
		  n    [0,m]
		*/
		//printf("%d %d\n",A[x][n],A[y][m]);
		printf("%.10f\n",Hash[make_pair(x,y)]=ans*1./(1ll*A[x][n]*A[y][m]));
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N];
int f[N],size[N],g[N],vis[N],A[2][N];
long long sum[N],B[2][N];
int n,m,Q,id,len,x,y,i,tot,ans,X,Y,u,v;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int dis){
	vis[x]=1;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=f[x])
	    f[a[x][i]]=x,DFS(a[x][i],dis+1);
}
void BFS(int x,int fa){
	size[x]=1;sum[x]=0;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa){
	  	if (a[x][i]==0) continue;
	  	if (X==x&&Y==a[x][i]) continue;
	  	if (X==a[x][i]&&Y==x) continue;
	  	int y=a[x][i];
	  	BFS(y,x);
	  	size[x]+=size[y];
	  	sum[x]+=sum[y]+size[y];
	  }
}
int main(){
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;f[i]=0;DFS(i,0);x=id;
	  	id=0;len=-1;f[x]=0;DFS(x,0);y=id;
	  	++tot;
	  	for (x=len/2;x;x--,y=f[y]);
	  	a[tot].push_back(y);
	  	a[tot].push_back(f[y]);
	  	X=y;Y=f[y];
	  	BFS(tot,0);
	  	x=get(i);
	  	A[0][x]=size[a[tot][0]];
			B[0][x]=sum[a[tot][0]]+1ll*(len/2)*A[0][x];
	  	A[1][x]=size[a[tot][1]];
			B[1][x]=sum[a[tot][1]]+1ll*((len+1)/2)*A[1][x];
	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		ans=0;
		for (u=0;u<2;u++)
		  for (v=0;v<2;v++)
		    ans+=1ll*A[u][x]*A[v][y]+B[u][x]+B[v][y];
		printf("%.10f\n",ans*1./(A[0][x]+A[1][x])/(A[0][y]+A[1][y]));
	}
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
vector<int>a[N],t[N];
int f[N],g[N],record[N],vis[N];
long long sum,ans;
vector<long long>A[N],B[N];
int n,m,Q,id,len,x,y,i,j,tot,u,v,flag,k;
int get(int u){return g[u]==u?u:g[u]=get(g[u]);}
void DFS(int x,int fa,int dis){
	vis[x]=1;
	if (flag==1) record[x]=dis;
	else if (flag==2) f[max(record[x],dis)]++;
	if (dis>len)
	  len=dis,id=x;
	for (int i=0;i<a[x].size();i++)
	  if (a[x][i]!=fa)
	    DFS(a[x][i],x,dis+1);
}
int main(){
	//freopen("d.in","r",stdin);
	scanf("%d%d%d",&n,&m,&Q);
	for (i=1;i<=n;i++) g[i]=i;
	for (i=1;i<=m;i++){
	  scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
		g[get(x)]=get(y);
	}
	tot=n;
	for (i=1;i<=n;i++)
	  if (!vis[i]){
	  	id=0;len=-1;flag=0;DFS(i,0,0);x=id;
	  	id=0;len=-1;flag=1;DFS(x,0,0);y=id;
	  	id=0;len=-1;flag=2;DFS(y,0,0);
	  	x=get(i);

	  	for (k=0;k<=len;k++)
	  	  t[x].push_back(f[k]);

	  	for (sum=k=0;k<=len;k++)
			  sum+=f[k],A[x].push_back(sum);
	  	for (sum=0,k=len;k>=0;k--)
			  sum+=f[k],B[x].push_back(sum);
	  	for (k=0;k<=len;k++) f[k]=0;

	  }

	while (Q--){
		scanf("%d%d",&x,&y);
		x=get(x);y=get(y);
		if (x==y) {puts("-1");continue;}
		if (t[x].size()<t[y].size()) swap(x,y);
		n=t[x].size()-1;m=t[y].size()-1;
		for (i=0;i<=n;i++) printf("%d ",t[x][i]);puts("");
		for (i=0;i<=m;i++) printf("%d ",t[y][i]);puts("");
		u=n-1-m;
		if (u>=0) ans+=1ll*A[x][u]*A[y][m]*n;
		++u;
		ans+=1ll*n*(1ll*m*(m+1)/2LL);

		for (i=u;i<=n;i++)
		  for (j=m-(u-i);j<=m;j++)
		    ans+=1ll*t[x][i]*t[y][j]*(i+j+1);
		/*u~n:
		  u    [m,m]
		  u+1  [m-1,m]
		  n    [0,m]
		*/

		printf("%.10f\n",ans*1./(1ll*A[x][u]*B[y][m]));
	}
}


#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
using namespace std;

#define mod 1000000007
#define mx 100005

vector<int> adj[mx];

int farthest[mx];

int comp[mx];
pair<int, int> tbest ;

void dfs(int x, int p, int d, int num) {

	comp[x] = num;
	farthest[x] = max(farthest[x],d);
	tbest = max(tbest, { d,x });
	for (auto u : adj[x]) {
		if (u == p) continue;
		dfs(u, x, d + 1, num);
	}
}

map<pair<int, int>, double> member;
vector<int> A[mx];
vector<long long> psum[mx];
double solve(int u, int v) {
	u = comp[u];
	v = comp[v];
	if (u == v) {

		return -1;
	}

	if (member.count({ min(u, v), max(u, v) })) {
		return member[{ min(u, v), max(u, v) }];
	}

	if (A[u].size() > A[v].size()) swap(u, v);

	int N = A[u].size();
	int M = A[v].size();
	long long tot = 0;

	double tot_num = (N - 1) * 1ll*(M - 1);

	long long maxi = max(A[u][N-1], A[v][N-1]);
	int L = 0;
	for (int i = 1;i < N;++i) {

		int l = 1, U = M - 1, mid, mi = M ;

		while (l <= U) {
			mid = (l + U) / 2;

			if (A[u][i] + A[v][mid] +1<= maxi)
				l = mid + 1;
			else {
				U = mid - 1;
				mi = mid;
			}
		}

		tot += (mi - 1) * 1ll * maxi;

		tot += psum[v][M - 1] - psum[v][mi - 1];
		tot += (A[u][i] +1) * 1ll * (M - 1 - (mi - 1));
	}
	long double ans = tot;
	ans /= tot_num;

	return member[{ min(u, v), max(u, v) }] = ans;
}

int main() {
	int n,m,q;

	memset(comp, -1, sizeof(comp));
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 0;i < m;++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	for (int i = 1;i <= n;++i) {
		if (comp[i] == -1) {
			tbest = { -1, 0 };
			dfs(i, -1, 0, i);

			int tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);

			tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);
		}
		A[i].push_back(0);
	}

	for (int i = 1;i <= n;++i) {
		A[comp[i]].push_back(farthest[i]);
	}

	for (int i = 1;i <= n;++i)
		sort(A[i].begin(), A[i].end());

	for (int i = 1;i <= n;++i) {
		int sz = A[i].size();
		psum[i].push_back(0);
		for (int j = 1;j < sz;++j)
			psum[i].push_back(psum[i][j - 1] + A[i][j]);
	}
	while (q--) {
		int u, v;
		scanf("%d%d", &u,  & v);
		printf("%.6lf\n", solve(u, v));
	}
	//puts()
}


#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
using namespace std;

#define mod 1000000007
#define mx 100005

vector<int> adj[mx];

int farthest[mx];

int comp[mx];
pair<int, int> tbest ;

void dfs(int x, int p, int d, int num) {

	comp[x] = num;
	farthest[x] = max(farthest[x],d);
	tbest = max(tbest, { d,x });
	for (auto u : adj[x]) {
		if (u == p) continue;
		dfs(u, x, d + 1, num);
	}
}

map<pair<int, int>, double> member;
vector<int> A[mx];
vector<long long> psum[mx];
double solve(int u, int v) {
	u = comp[u];
	v = comp[v];
	if (u == v) {

		return -1;
	}

	if (member.count({ min(u, v), max(u, v) })) {
		return member[{ min(u, v), max(u, v) }];
	}

	if (A[u].size() > A[v].size()) swap(u, v);

	int N = A[u].size();
	int M = A[v].size();
	long long tot = 0;

	double tot_num = (N - 1) * 1ll*(M - 1);

	long long maxi = max(A[u][N-1], A[v][N-1]);
	int L = 0;
	for (int i = 1;i < N;++i) {

		int l = 0, U = M - 1, mid, mi = M - 1;

		while (l <= U) {
			mid = (l + U) / 2;

			if (A[u][i] + A[v][mid] +1<= maxi)
				l = mid + 1;
			else {
				U = mid - 1;
				mi = mid;
			}
		}
		if (mi == 0)mi++;
		tot += (mi - 1) * 1ll * maxi;

		tot += psum[v][M - 1] - psum[v][mi - 1];
		tot += (A[u][i] +1) * 1ll * (M - 1 - (mi - 1));
	}
	long double ans = tot;
	ans /= tot_num;

	return member[{ min(u, v), max(u, v) }] = ans;
}

int main() {
	int n,m,q;

	memset(comp, -1, sizeof(comp));
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 0;i < m;++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	for (int i = 1;i <= n;++i) {
		if (comp[i] == -1) {
			tbest = { -1, 0 };
			dfs(i, -1, 0, i);

			int tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);

			tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);
		}
		A[i].push_back(0);
	}

	for (int i = 1;i <= n;++i) {
		A[comp[i]].push_back(farthest[i]);
	}

	for (int i = 1;i <= n;++i)
		sort(A[i].begin(), A[i].end());

	for (int i = 1;i <= n;++i) {
		int sz = A[i].size();
		psum[i].push_back(0);
		for (int j = 1;j < sz;++j)
			psum[i].push_back(psum[i][j - 1] + A[i][j]);
	}
	while (q--) {
		int u, v;
		scanf("%d%d", &u,  & v);
		printf("%.6lf\n", solve(u, v));
	}
	//puts()
}


#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
using namespace std;

#define mod 1000000007
#define mx 100005

vector<int> adj[mx];

int farthest[mx];

int comp[mx];
pair<int, int> tbest ;

void dfs(int x, int p, int d, int num) {

	comp[x] = num;
	farthest[x] = max(farthest[x],d);
	tbest = max(tbest, { d,x });
	for (auto u : adj[x]) {
		if (u == p) continue;
		dfs(u, x, d + 1, num);
	}
}

map<pair<int, int>, double> member;
vector<int> A[mx];
vector<long long> psum[mx];
double solve(int u, int v) {
	u = comp[u];
	v = comp[v];
	if (u == v) {

		return -1;
	}

	if (member.count({ min(u, v), max(u, v) })) {
		return member[{ min(u, v), max(u, v) }];
	}

	if (A[u].size() > A[v].size()) swap(u, v);

	int N = A[u].size();
	int M = A[v].size();
	long long tot = 0;

	double tot_num = (N - 1) * 1ll*(M - 1);

	long long maxi = max(A[u][N-1], A[v][N-1]);
	int L = 0;
	for (int i = 1;i < N;++i) {

		int l = 0, U = M - 1, mid, mi = M - 1;

		while (l <= U) {
			mid = (l + U) / 2;

			if (A[u][i] + A[v][mid] +1<= maxi)
				l = mid + 1;
			else {
				U = mid - 1;
				mi = mid;
			}
		}
		tot += (mi - 1) * 1ll * maxi;
		tot += psum[v][M - 1] - psum[v][mi - 1];
		tot += (A[u][i] +1) * 1ll * (M - 1 - (mi - 1));
	}
	long double ans = tot;
	ans /= tot_num;

	return member[{ min(u, v), max(u, v) }] = ans;
}

int main() {
	int n,m,q;

	memset(comp, -1, sizeof(comp));
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 0;i < m;++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	for (int i = 1;i <= n;++i) {
		if (comp[i] == -1) {
			tbest = { -1, 0 };
			dfs(i, -1, 0, i);

			int tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);

			tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);
		}
		A[i].push_back(0);
	}

	for (int i = 1;i <= n;++i) {
		A[comp[i]].push_back(farthest[i]);
	}

	for (int i = 1;i <= n;++i)
		sort(A[i].begin(), A[i].end());

	for (int i = 1;i <= n;++i) {
		int sz = A[i].size();
		psum[i].push_back(0);
		for (int j = 1;j < sz;++j)
			psum[i].push_back(psum[i][j - 1] + A[i][j]);
	}
	while (q--) {
		int u, v;
		scanf("%d%d", &u,  & v);
		printf("%.6lf\n", solve(u, v));
	}
	//puts()
}


#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
using namespace std;

#define mod 1000000007
#define mx 100005

vector<int> adj[mx];

int farthest[mx];

int comp[mx];
pair<int, int> tbest ;

void dfs(int x, int p, int d, int num) {

	comp[x] = num;
	farthest[x] = max(farthest[x],d);
	tbest = max(tbest, { d,x });
	for (auto u : adj[x]) {
		if (u == p) continue;
		dfs(u, x, d + 1, num);
	}
}

map<pair<int, int>, double> member;
vector<int> A[mx];
vector<long long> psum[mx];
double solve(int u, int v) {
	u = comp[u];
	v = comp[v];
	if (u == v) {

		return -1;
	}

	if (member.count({ min(u, v), max(u, v) })) {
		return member[{ min(u, v), max(u, v) }];
	}

	if (A[u].size() > A[v].size()) swap(u, v);

	int N = A[u].size();
	int M = A[v].size();
	long long tot = 0;

	double tot_num = (N - 1) * 1ll*(M - 1);

	long long maxi = max(A[u][N-1], A[v][M-1]);
	int L = 0;
	for (int i = 1;i < N;++i) {

		int l = 1, U = M - 1, mid, mi = M ;

		while (l <= U) {
			mid = (l + U) / 2;

			if (A[u][i] + A[v][mid] +1<= maxi)
				l = mid + 1;
			else {
				U = mid - 1;
				mi = mid;
			}
		}

		tot += (mi - 1) * 1ll * maxi;

		tot += psum[v][M - 1] - psum[v][mi - 1];
		tot += (A[u][i] +1) * 1ll * (M - 1 - (mi - 1));
	}
	long double ans = tot;
	ans /= tot_num;

	return member[{ min(u, v), max(u, v) }] = ans;
}

int main() {
	int n,m,q;

	memset(comp, -1, sizeof(comp));
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 0;i < m;++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	for (int i = 1;i <= n;++i) {
		if (comp[i] == -1) {
			tbest = { -1, 0 };
			dfs(i, -1, 0, i);

			int tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);

			tx = tbest.second;
			tbest = { -1, 0 };
			dfs(tx, -1, 0, i);
		}
		A[i].push_back(0);
	}

	for (int i = 1;i <= n;++i) {
		A[comp[i]].push_back(farthest[i]);
	}

	for (int i = 1;i <= n;++i)
		sort(A[i].begin(), A[i].end());

	for (int i = 1;i <= n;++i) {
		int sz = A[i].size();
		psum[i].push_back(0);
		for (int j = 1;j < sz;++j)
			psum[i].push_back(psum[i][j - 1] + A[i][j]);
	}
	while (q--) {
		int u, v;
		scanf("%d%d", &u,  & v);
		printf("%.6lf\n", solve(u, v));
	}
	//puts()
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, v) for(auto& a : v)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

ll big = 1000000007ll;
ll big2 = 1000000009ll;
ll n,m,q,T,k;

vector<vector<ll> > C(100001 , vector<ll>());
unordered_map<ll,ll> M;
vector<ll> D;
vector<ld> ex;
ll sum = 0;
ll nodes = 0;
ll bel[100001] = {0};
ll now = 0;

ll has(ll i, ll par){
    return (par+1)*200000 + i;
}

ll dp(ll i, ll par){
ll h = has(i,par);
if(M.find(h) != M.end())return M[h];
ll ans = 0;

for(ll c1 = 0; c1 < C[i].size(); c1++){
    ll a = C[i][c1];
    if(a != par){
        ans = max(ans , 1+dp(a,i));
    }
}
M[h] = ans;
return ans;
}

void dfs(ll i, ll par){
    bel[i] = now;
    sum += D[i];
    nodes++;
    for(ll c1 = 0; c1 < C[i].size(); c1++){
        ll a = C[i][c1];
        if(a != par){
            dfs(a,i);
        }
    }
}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("autput.txt","w",stdout);

    ll a,b,c,d;

    cin >> n >> m >> q;

    for(ll c1 = 0; c1 < m; c1++){
        cin >> a >> b;
        a--;
        b--;
        C[a].push_back(b);
        C[b].push_back(a);
    }
    for(ll c1 = 0; c1 < n; c1++){
        D.push_back(dp(c1,-1));
        bel[c1] = -1;
    }

    for(ll c1 = 0; c1 < n; c1++){
        if(bel[c1] == -1){
            sum = 0;
            nodes = 0;
            dfs(c1,-1);
            now++;
            ex.push_back(ld(sum) / ld(nodes));
            //cout << sum << " " << nodes << "  gf\n";
        }
    }

    for(ll c1 = 0; c1 < q; c1++){
        cin >> a >> b;
        a--;
        b--;

       // cout << bel[a] << " " << bel[b] <<  "\n";

        if(bel[a] == bel[b]){
            cout << "-1\n";
        }
        else{
            cout << setprecision(18) << ex[bel[a]]+ex[bel[b]] + 1.0 << "\n";

        }
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, v) for(auto& a : v)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

ll big = 1000000007ll;
ll big2 = 1000000009ll;
ll n,m,q,T,k;

vector<vector<ll> > C(100001 , vector<ll>());
unordered_map<ll,ll> M;
vector<ll> D;
vector<ld> ex;
vector<ll> diam;

vector<vector<ll> > CS(100001 , vector<ll>());

vector<vector<ll> > D2(100001 , vector<ll>());
vector<ll> temp;

ll sum = 0;
ll nodes = 0;
ll bel[100001] = {0};
ll now = 0;
ll longest = 0;

ll has(ll i, ll par){
    return (par+1)*200000 + i;
}

ll dp(ll i, ll par){
ll h = has(i,par);
if(M.find(h) != M.end())return M[h];
ll ans = 0;

for(ll c1 = 0; c1 < C[i].size(); c1++){
    ll a = C[i][c1];
    if(a != par){
        ans = max(ans , 1+dp(a,i));
    }
}
M[h] = ans;
return ans;
}

void dfs(ll i, ll par){
    bel[i] = now;
    sum += D[i];
    temp.push_back(D[i]);
    longest = max(longest , D[i]);
    nodes++;
    for(ll c1 = 0; c1 < C[i].size(); c1++){
        ll a = C[i][c1];
        if(a != par){
            dfs(a,i);
        }
    }
}

ll has2(ll i, ll j){
ll i2 = min(i,j);
ll j2 = max(i,j);
return 100001 + i2 + j2;
}

ll bs(ll ind , ll k){

ll l = 0;
ll r = D2[ind].size();

if(D2[ind][l] >= k)return -1;

while(l < r-1){

    ll mid = (l+r)/2;
    if(D2[ind][mid] < k){
        l = mid;
    }
    else{
        r = mid;
    }
}

return l;

}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("autput.txt","w",stdout);

    ll a,b,c,d;

    cin >> n >> m >> q;

    for(ll c1 = 0; c1 < m; c1++){
        cin >> a >> b;
        a--;
        b--;
        C[a].push_back(b);
        C[b].push_back(a);
    }
    for(ll c1 = 0; c1 < n; c1++){
        D.push_back(dp(c1,-1));
        bel[c1] = -1;
    }

    for(ll c1 = 0; c1 < n; c1++){
        if(bel[c1] == -1){
            sum = 0;
            nodes = 0;
            longest = 0;
            temp.clear();
            dfs(c1,-1);
            now++;
            sort(all(temp));
            for(ll c2 = 0; c2 < temp.size(); c2++){
                D2[now-1].push_back(temp[c2]);
            }
            diam.push_back(longest);
            ex.push_back(ld(sum) / ld(nodes));
            CS[now-1].push_back(0);
            for(ll c2 = 0; c2 < temp.size(); c2++){
                CS[now-1].push_back(CS[now-1][c2] + D2[now-1][c2]);
            }
            //cout << sum << " " << nodes << "  gf\n";
        }
    }

    unordered_map<ll,ld> M2;

    for(ll c1 = 0; c1 < q; c1++){
        cin >> a >> b;
        a--;
        b--;

       // cout << bel[a] << " " << bel[b] <<  "\n";

        if(bel[a] == bel[b]){
            cout << "-1\n";
        }
        else{

            ll h = has2(a,b);
            if(M2.find(h) != M2.end()){
                cout << setprecision(18) << M2[h] << "\n";
            }
            else{
                a = bel[a];
                b = bel[b];
                  ll a2,b2;
                  if(D2[a].size() < D2[b].size()){
                    a2 = a;
                    b2 = b;
                  }
                  else{
                    a2 = b;
                    b2 = a;
                  }
                  ll ans = 0;
                  ll dia = max(diam[a],diam[b]);

                  for(ll c2 = 0; c2 < D2[a2].size(); c2++){
                    ll a = D2[a2][c2];
                    ll i2 = bs(b2 , dia - 1 - a);
                    ans += CS[b2][D2[b2].size()] - CS[b2][i2+1] + (a+1) * (D2[b2].size() - i2 - 1);
                    ans += (i2+1) * dia;
                   // cout << i2 << " " << CS[b2][D2[b2].size()] - CS[b2][i2+1] + a + D2[b2].size() - i2 - 1 << "  fd\n";  //
                  }

                  ld ans2 = ld(ans) / ld(D2[a2].size() * D2[b2].size());
                  M2[h] = ans2;

                cout << setprecision(18) << M2[h] << "\n";

            }
        }
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, v) for(auto& a : v)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

ll big = 1000000007ll;
ll big2 = 1000000009ll;
ll n,m,q,T,k;

vector<vector<ll> > C(100001 , vector<ll>());
unordered_map<ll,ll> M;
vector<ll> D;
vector<ld> ex;
vector<ll> diam;

vector<vector<ll> > CS(100001 , vector<ll>());

vector<vector<ll> > D2(100001 , vector<ll>());
vector<ll> temp;

ll sum = 0;
ll nodes = 0;
ll bel[100001] = {0};
ll now = 0;
ll longest = 0;

ll has(ll i, ll par){
    return (par+1)*200000 + i;
}

ll dp(ll i, ll par){
ll h = has(i,par);
if(M.find(h) != M.end())return M[h];
ll ans = 0;

for(ll c1 = 0; c1 < C[i].size(); c1++){
    ll a = C[i][c1];
    if(a != par){
        ans = max(ans , 1+dp(a,i));
    }
}
M[h] = ans;
return ans;
}

void dfs(ll i, ll par){
    bel[i] = now;
    sum += D[i];
    temp.push_back(D[i]);
    longest = max(longest , D[i]);
    nodes++;
    for(ll c1 = 0; c1 < C[i].size(); c1++){
        ll a = C[i][c1];
        if(a != par){
            dfs(a,i);
        }
    }
}

ll has2(ll i, ll j){
ll i2 = min(i,j);
ll j2 = max(i,j);
return 100001 * i2 + j2;
}

ll bs(ll ind , ll k){

ll l = 0;
ll r = D2[ind].size();

if(D2[ind][l] >= k)return -1;

while(l < r-1){

    ll mid = (l+r)/2;
    if(D2[ind][mid] < k){
        l = mid;
    }
    else{
        r = mid;
    }
}

return l;

}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("autput.txt","w",stdout);

    ll a,b,c,d;

    cin >> n >> m >> q;

    for(ll c1 = 0; c1 < m; c1++){
        cin >> a >> b;
        a--;
        b--;
        C[a].push_back(b);
        C[b].push_back(a);
    }
    for(ll c1 = 0; c1 < n; c1++){
        D.push_back(dp(c1,-1));
        bel[c1] = -1;
    }

    for(ll c1 = 0; c1 < n; c1++){
        if(bel[c1] == -1){
            sum = 0;
            nodes = 0;
            longest = 0;
            temp.clear();
            dfs(c1,-1);
            now++;
            sort(all(temp));
            for(ll c2 = 0; c2 < temp.size(); c2++){
                D2[now-1].push_back(temp[c2]);
            }
            diam.push_back(longest);
            ex.push_back(ld(sum) / ld(nodes));
            CS[now-1].push_back(0);
            for(ll c2 = 0; c2 < temp.size(); c2++){
                CS[now-1].push_back(CS[now-1][c2] + D2[now-1][c2]);
            }
            //cout << sum << " " << nodes << "  gf\n";
        }
    }

    unordered_map<ll,ld> M2;

    for(ll c1 = 0; c1 < q; c1++){
        cin >> a >> b;
        a--;
        b--;

       // cout << bel[a] << " " << bel[b] <<  "\n";

        if(bel[a] == bel[b]){
            cout << "-1\n";
        }
        else{

            a = bel[a];
            b = bel[b];

            ll h = has2(a,b);
            if(M2.find(h) != M2.end()){
                cout << setprecision(18) << M2[h] << "\n";
            }
            else{
                  ll a2,b2;
                  if(D2[a].size() < D2[b].size()){
                    a2 = a;
                    b2 = b;
                  }
                  else{
                    a2 = b;
                    b2 = a;
                  }
                  ll ans = 0;
                  ll dia = max(diam[a],diam[b]);

                  for(ll c2 = 0; c2 < D2[a2].size(); c2++){
                    ll a3 = D2[a2][c2];
                    ll i2 = bs(b2 , dia - 1 - a3);
                    ans += CS[b2][D2[b2].size()] - CS[b2][i2+1] + (a3+1) * (D2[b2].size() - i2 - 1);
                    ans += (i2+1) * dia;
                   // cout << i2 << " " << CS[b2][D2[b2].size()] - CS[b2][i2+1] + a + D2[b2].size() - i2 - 1 << "  fd\n";  //
                  }

                  ld ans2 = ld(ans) / ld(D2[a2].size() * D2[b2].size());
                  M2[h] = ans2;

                cout << setprecision(18) << M2[h] << "\n";

            }
        }
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, v) for(auto& a : v)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

ll big = 1000000007ll;
ll big2 = 1000000009ll;
ll n,m,q,T,k;

vector<vector<ll> > C(100001 , vector<ll>());
unordered_map<ll,ll> M;
vector<ll> D;
vector<ld> ex;
vector<ll> diam;

vector<vector<ll> > CS(100001 , vector<ll>());

vector<vector<ll> > D2(100001 , vector<ll>());
vector<ll> temp;

ll sum = 0;
ll nodes = 0;
ll bel[100001] = {0};
ll now = 0;
ll longest = 0;

ll has(ll i, ll par){
    return (par+1)*200000 + i;
}

ll dp(ll i, ll par){
ll h = has(i,par);
if(M.find(h) != M.end())return M[h];
ll ans = 0;

for(ll c1 = 0; c1 < C[i].size(); c1++){
    ll a = C[i][c1];
    if(a != par){
        ans = max(ans , 1+dp(a,i));
    }
}
M[h] = ans;
return ans;
}

void dfs(ll i, ll par){
    bel[i] = now;
    sum += D[i];
    temp.push_back(D[i]);
    longest = max(longest , D[i]);
    nodes++;
    for(ll c1 = 0; c1 < C[i].size(); c1++){
        ll a = C[i][c1];
        if(a != par){
            dfs(a,i);
        }
    }
}

ll has2(ll i, ll j){
ll i2 = min(i,j);
ll j2 = max(i,j);
return 100001 + i2 + j2;
}

ll bs(ll ind , ll k){

ll l = 0;
ll r = D2[ind].size();

if(D2[ind][l] >= k)return -1;

while(l < r-1){

    ll mid = (l+r)/2;
    if(D2[ind][mid] < k){
        l = mid;
    }
    else{
        r = mid;
    }
}

return l;

}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("autput.txt","w",stdout);

    ll a,b,c,d;

    cin >> n >> m >> q;

    for(ll c1 = 0; c1 < m; c1++){
        cin >> a >> b;
        a--;
        b--;
        C[a].push_back(b);
        C[b].push_back(a);
    }
    for(ll c1 = 0; c1 < n; c1++){
        D.push_back(dp(c1,-1));
        bel[c1] = -1;
    }

    for(ll c1 = 0; c1 < n; c1++){
        if(bel[c1] == -1){
            sum = 0;
            nodes = 0;
            longest = 0;
            temp.clear();
            dfs(c1,-1);
            now++;
            sort(all(temp));
            D2.push_back(temp);
            diam.push_back(longest);
            ex.push_back(ld(sum) / ld(nodes));
            CS[now-1].push_back(0);
            for(ll c2 = 0; c2 < temp.size(); c2++){
                CS[now-1].push_back(CS[now-1][c2] + D2[now-1][c2]);
            }
            //cout << sum << " " << nodes << "  gf\n";
        }
    }

    unordered_map<ll,ll> M2;

    for(ll c1 = 0; c1 < q; c1++){
        cin >> a >> b;
        a--;
        b--;

       // cout << bel[a] << " " << bel[b] <<  "\n";

        if(bel[a] == bel[b]){
            cout << "-1\n";
        }
        else{

            ll h = has2(a,b);
            if(M2.find(h) != M2.end()){
                cout << setprecision(18) << M2[h] << "\n";
            }
            else{
                a = bel[a];
                b = bel[b];
                  ll a2,b2;
                  if(D2[a].size() < D2[b].size()){
                    a2 = a;
                    b2 = b;
                  }
                  else{
                    a2 = b;
                    b2 = a;
                  }

                  ll ans = 0;

                  ll dia = max(diam[a],diam[b]);

                  for(ll c2 = 0; c2 < D2[a2].size(); c2++){
                    ll a = D2[a2][c2];

                    ll i2 = bs(b2 , dia - 1 - a);

                    ans += CS[b2][D2[b2].size()] - CS[b2][i2+1] + a + 1;
                    ans += i2 * dia;

                  }

                  ld ans2 = ld(ans) / ld(D2[a2].size() * D2[b2].size());
                  M2[h] = ans2;

                cout << setprecision(18) << M2[h] << "\n";

            }
        }
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, v) for(auto& a : v)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

ll big = 1000000007ll;
ll big2 = 1000000009ll;
ll n,m,q,T,k;

vector<vector<ll> > C(100001 , vector<ll>());
unordered_map<ll,ll> M;
vector<ll> D;
vector<ld> ex;
vector<ll> diam;

vector<vector<ll> > CS(100001 , vector<ll>());

vector<vector<ll> > D2(100001 , vector<ll>());
vector<ll> temp;

ll sum = 0;
ll nodes = 0;
ll bel[100001] = {0};
ll now = 0;
ll longest = 0;

ll has(ll i, ll par){
    return (par+1)*200000 + i;
}

ll dp(ll i, ll par){
ll h = has(i,par);
if(M.find(h) != M.end())return M[h];
ll ans = 0;

for(ll c1 = 0; c1 < C[i].size(); c1++){
    ll a = C[i][c1];
    if(a != par){
        ans = max(ans , 1+dp(a,i));
    }
}
M[h] = ans;
return ans;
}

void dfs(ll i, ll par){
    bel[i] = now;
    sum += D[i];
    temp.push_back(D[i]);
    longest = max(longest , D[i]);
    nodes++;
    for(ll c1 = 0; c1 < C[i].size(); c1++){
        ll a = C[i][c1];
        if(a != par){
            dfs(a,i);
        }
    }
}

ll has2(ll i, ll j){
ll i2 = min(i,j);
ll j2 = max(i,j);
return 100001 + i2 + j2;
}

ll bs(ll ind , ll k){

ll l = 0;
ll r = D2[ind].size();

if(D2[ind][l] >= k)return -1;

while(l < r-1){

    ll mid = (l+r)/2;
    if(D2[ind][mid] < k){
        l = mid;
    }
    else{
        r = mid;
    }
}

return l;

}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("autput.txt","w",stdout);

    ll a,b,c,d;

    cin >> n >> m >> q;

    for(ll c1 = 0; c1 < m; c1++){
        cin >> a >> b;
        a--;
        b--;
        C[a].push_back(b);
        C[b].push_back(a);
    }
    for(ll c1 = 0; c1 < n; c1++){
        D.push_back(dp(c1,-1));
        bel[c1] = -1;
    }

    for(ll c1 = 0; c1 < n; c1++){
        if(bel[c1] == -1){
            sum = 0;
            nodes = 0;
            longest = 0;
            temp.clear();
            dfs(c1,-1);
            now++;
            sort(all(temp));
            for(ll c2 = 0; c2 < temp.size(); c2++){
                D2[now-1].push_back(temp[c2]);
            }
            diam.push_back(longest);
            ex.push_back(ld(sum) / ld(nodes));
            CS[now-1].push_back(0);
            for(ll c2 = 0; c2 < temp.size(); c2++){
                CS[now-1].push_back(CS[now-1][c2] + D2[now-1][c2]);
            }
            //cout << sum << " " << nodes << "  gf\n";
        }
    }

    unordered_map<ll,ld> M2;

    for(ll c1 = 0; c1 < q; c1++){
        cin >> a >> b;
        a--;
        b--;

       // cout << bel[a] << " " << bel[b] <<  "\n";

        if(bel[a] == bel[b]){
            cout << "-1\n";
        }
        else{

            ll h = has2(a,b);
            if(M2.find(h) != M2.end()){
                cout << setprecision(18) << M2[h] << "\n";
            }
            else{
                a = bel[a];
                b = bel[b];
                  ll a2,b2;
                  if(D2[a].size() < D2[b].size()){
                    a2 = a;
                    b2 = b;
                  }
                  else{
                    a2 = b;
                    b2 = a;
                  }

                  ll ans = 0;

                  ll dia = max(diam[a],diam[b]);

                  for(ll c2 = 0; c2 < D2[a2].size(); c2++){
                    ll a = D2[a2][c2];

                    ll i2 = bs(b2 , dia - 1 - a);

                    ans += CS[b2][D2[b2].size()] - CS[b2][i2+1] + a + D2[b2].size() - i2 - 1;

                    ans += (i2+1) * dia;

                  }

                //cout << dia << " " << D2[a2].size() * D2[b2].size() << "  gf\n";

                  ld ans2 = ld(ans) / ld(D2[a2].size() * D2[b2].size());
                  M2[h] = ans2;

                cout << setprecision(18) << M2[h] << "\n";

            }
        }
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, v) for(auto& a : v)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

ll big = 1000000007ll;
ll big2 = 1000000009ll;
ll n,m,q,T,k;

vector<vector<ll> > C(100001 , vector<ll>());
unordered_map<ll,ll> M;
vector<ll> D;
vector<ld> ex;
vector<ll> diam;

vector<vector<ll> > CS(100001 , vector<ll>());

vector<vector<ll> > D2(100001 , vector<ll>());
vector<ll> temp;

ll sum = 0;
ll nodes = 0;
ll bel[100001] = {0};
ll now = 0;
ll longest = 0;

ll has(ll i, ll par){
    return (par+1)*200000 + i;
}

ll dp(ll i, ll par){
ll h = has(i,par);
if(M.find(h) != M.end())return M[h];
ll ans = 0;

for(ll c1 = 0; c1 < C[i].size(); c1++){
    ll a = C[i][c1];
    if(a != par){
        ans = max(ans , 1+dp(a,i));
    }
}
M[h] = ans;
return ans;
}

void dfs(ll i, ll par){
    bel[i] = now;
    sum += D[i];
    temp.push_back(D[i]);
    longest = max(longest , D[i]);
    nodes++;
    for(ll c1 = 0; c1 < C[i].size(); c1++){
        ll a = C[i][c1];
        if(a != par){
            dfs(a,i);
        }
    }
}

ll has2(ll i, ll j){
ll i2 = min(i,j);
ll j2 = max(i,j);
return 100001 + i2 + j2;
}

ll bs(ll ind , ll k){

ll l = 0;
ll r = D2[ind].size();

if(D2[ind][l] >= k)return -1;

while(l < r-1){

    ll mid = (l+r)/2;
    if(D2[ind][mid] < k){
        l = mid;
    }
    else{
        r = mid;
    }
}

return l;

}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("autput.txt","w",stdout);

    ll a,b,c,d;

    cin >> n >> m >> q;

    for(ll c1 = 0; c1 < m; c1++){
        cin >> a >> b;
        a--;
        b--;
        C[a].push_back(b);
        C[b].push_back(a);
    }
    for(ll c1 = 0; c1 < n; c1++){
        D.push_back(dp(c1,-1));
        bel[c1] = -1;
    }

    for(ll c1 = 0; c1 < n; c1++){
        if(bel[c1] == -1){
            sum = 0;
            nodes = 0;
            longest = 0;
            temp.clear();
            dfs(c1,-1);
            now++;
            sort(all(temp));
            for(ll c2 = 0; c2 < temp.size(); c2++){
                D2[now-1].push_back(temp[c2]);
            }
            diam.push_back(longest);
            ex.push_back(ld(sum) / ld(nodes));
            CS[now-1].push_back(0);
            for(ll c2 = 0; c2 < temp.size(); c2++){
                CS[now-1].push_back(CS[now-1][c2] + D2[now-1][c2]);
            }
            //cout << sum << " " << nodes << "  gf\n";
        }
    }

    unordered_map<ll,ld> M2;

    for(ll c1 = 0; c1 < q; c1++){
        cin >> a >> b;
        a--;
        b--;

       // cout << bel[a] << " " << bel[b] <<  "\n";

        if(bel[a] == bel[b]){
            cout << "-1\n";
        }
        else{

            a = bel[a];
            b = bel[b];

            ll h = has2(a,b);
            if(M2.find(h) != M2.end()){
                cout << setprecision(18) << M2[h] << "\n";
            }
            else{
                  ll a2,b2;
                  if(D2[a].size() < D2[b].size()){
                    a2 = a;
                    b2 = b;
                  }
                  else{
                    a2 = b;
                    b2 = a;
                  }
                  ll ans = 0;
                  ll dia = max(diam[a],diam[b]);

                  for(ll c2 = 0; c2 < D2[a2].size(); c2++){
                    ll a3 = D2[a2][c2];
                    ll i2 = bs(b2 , dia - 1 - a3);
                    ans += CS[b2][D2[b2].size()] - CS[b2][i2+1] + (a3+1) * (D2[b2].size() - i2 - 1);
                    ans += (i2+1) * dia;
                   // cout << i2 << " " << CS[b2][D2[b2].size()] - CS[b2][i2+1] + a + D2[b2].size() - i2 - 1 << "  fd\n";  //
                  }

                  ld ans2 = ld(ans) / ld(D2[a2].size() * D2[b2].size());
                  M2[h] = ans2;

                cout << setprecision(18) << M2[h] << "\n";

            }
        }
    }

    return 0;
}


/// 求森林间链接一条新的边之后，两棵子树中每个点到树上最远距离的期望
/// 枚举一颗子树的所有点， 如果链接之后整棵树的直径变长 dis[l] + dis[r] + 1 > max(d[l], d[r])
/// 后半部分的期望会改变，以此前缀和二分
/**
 * @Samaritan
 */
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define pb emplace_back
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define PLI pair<LL, int>

LL quick_pow (LL a, LL b, LL mod) {
    LL ans = 1, base = a;
    while (b) {
        if (b & 1) (ans *= base) %= mod;
        b >>= 1;
        (base *= base) %= mod;
    }
    return ans;
}
void gcd(LL a, LL b, LL &d, LL &x, LL &y) {
    if (!b) {
        d = a; x = 1; y = 0;
    } else {
        gcd(b, a % b, d, y, x);
        y -= x * (a / b);
    }
}
LL get_inv(LL a, LL n) {
    LL d, x, y;
    gcd(a, n, d, x, y);
    return d == 1 ? (x + n) % n : -1;
}
inline int log2(const float &x) {
    return ((unsigned &) x >> 23 & 255) - 127;
}
template <typename type>
void show(type arr[], int len) {
    for (int i = 0; i <= len; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
}
const int mod = 1e9 + 7;
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int logN = 20;
const int INF = 1e7;

struct Edge {
    int v, nxt;
} edge[N << 1];
int head[N], edge_cnt;
inline void add_edge(int u, int v) {
    edge[edge_cnt] = {v, head[u]};
    head[u] = edge_cnt++;
}
int belong[N], belong_cnt;
/// 每一个点在自己子树里到最远点的距离
int vertice_dis[N];
/// 每一棵子树里的直径长度
int diameter[N];
/// 每一个子树里的点到最远点的距离，前缀和
vector<int> dis[N];
vector<int> pre[N];
void init(int n) {
    memset(head, -1, sizeof(head[0]) * (n + 3));
    edge_cnt = 0;
    belong_cnt = 0;
}
/// 搜索直径
int diameter_length, st, ed;
void dfs_d(int now, int par, int belong_id, int dep) {
    belong[now] = belong_id;
    if (dep > diameter_length) {
        diameter_length = dep;
        st = now;
    }
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs_d(to, now, belong_id, dep + 1);
        }
    }
}
void dfs(int now, int par, int dep) {
    vertice_dis[now] = max(vertice_dis[now], dep);
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs(to, now, dep + 1);
        }
    }
}
map<PII, double> cache;

int main() {
    int n, m, q;
    scanf("%d %d %d", &n, &m, &q);
    init(n);
    int l, r;
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &l, &r);
        add_edge(l, r); add_edge(r, l);
    }
    for (int i = 1; i <= n; ++i) if (!belong[i]) {
        st = i;
        diameter_length = 0;
        dfs_d(i, -1, ++belong_cnt, 0);
        ed = st;
        st = i;
        diameter_length = 0;
        dfs_d(ed, -1, belong_cnt, 0);
        diameter[belong_cnt] = diameter_length;
        dfs(st, -1, 0);
        dfs(ed, -1, 0);
    }
    for (int i = 1; i <= n; ++i) {
        dis[ belong[i] ].pb(vertice_dis[i]);
    }
    for (int i = 1; i <= belong_cnt; ++i) {
        sort (dis[i].begin(), dis[i].end());
        pre[i].resize(dis[i].size());
        pre[i][0] = dis[i][0];
        for (int j = 1; j < dis[i].size(); ++j) {
            pre[i][j] = pre[i][j - 1] + dis[i][j];
        }
    }
//    for (int i = 1; i <= belong_cnt; ++i) {
//        cout << "now : ";
//        for (int j : dis[i]) cout << j << " "; cout << endl;
//    }
    while (q--) {
        scanf("%d %d", &l, &r);
        l = belong[l]; r = belong[r];
        if (l == r) puts("-1");
        else if (cache.count({l, r})) printf("%.10f\n", cache[{l, r}]);
        else {
            if (dis[l].size() > dis[r].size()) swap(l, r);
            double ans = 0.0;
            int max_diameter = max(diameter[l], diameter[r]);

            for (int i : dis[l]) {
                int pos = upper_bound(dis[r].begin(), dis[r].end(), max_diameter - i - 1) - dis[r].begin();
                if (pos == dis[r].size()) ans += max_diameter * dis[r].size() * 1.0;
                else
                    ans += max_diameter * pos * 1.0 + (i + 1) * (dis[r].size() - pos) + pre[r].back() - (pos == 0 ? 0 : pre[r][pos - 1]);
            }
            ans /= (dis[l].size() * dis[r].size() * 1.0);
            cache[{l, r}] = ans;
            printf("%.10f\n", ans);
        }
    }
    return 0;
}


///
/**
 * @Samaritan
 */
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define pb emplace_back
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define PLI pair<LL, int>

LL quick_pow (LL a, LL b, LL mod) {
    LL ans = 1, base = a;
    while (b) {
        if (b & 1) (ans *= base) %= mod;
        b >>= 1;
        (base *= base) %= mod;
    }
    return ans;
}
void gcd(LL a, LL b, LL &d, LL &x, LL &y) {
    if (!b) {
        d = a; x = 1; y = 0;
    } else {
        gcd(b, a % b, d, y, x);
        y -= x * (a / b);
    }
}
LL get_inv(LL a, LL n) {
    LL d, x, y;
    gcd(a, n, d, x, y);
    return d == 1 ? (x + n) % n : -1;
}
inline int log2(const float &x) {
    return ((unsigned &) x >> 23 & 255) - 127;
}
template <typename type>
void show(type arr[], int len) {
    for (int i = 0; i <= len; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
}
const int mod = 1e9 + 7;
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int logN = 20;
const int INF = 1e7;

struct Edge {
    int v, nxt;
} edge[N << 1];
int head[N], edge_cnt;
inline void add_edge(int u, int v) {
    edge[edge_cnt] = {v, head[u]};
    head[u] = edge_cnt++;
}
int belong[N], belong_cnt;
/// 每一个点在自己子树里到最远点的距离
int vertice_dis[N];
/// 每一棵子树里的直径长度
int diameter[N];
/// 每一个子树里的点到最远点的距离，前缀和
vector<int> dis[N];
vector<int> pre[N];
void init(int n) {
    memset(head, -1, sizeof(head[0]) * (n + 3));
    edge_cnt = 0;
    belong_cnt = 0;
}
/// 搜索直径
int diameter_length, st, ed;
void dfs_d(int now, int par, int belong_id, int dep) {
    belong[now] = belong_id;
    if (dep > diameter_length) {
        diameter_length = dep;
        st = now;
    }
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs_d(to, now, belong_id, dep + 1);
        }
    }
}
void dfs(int now, int par, int dep) {
    vertice_dis[now] = max(vertice_dis[now], dep);
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs(to, now, dep + 1);
        }
    }
}
map<PII, double> cache;

int main() {
    int n, m, q;
    scanf("%d %d %d", &n, &m, &q);
    init(n);
    int l, r;
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &l, &r);
        add_edge(l, r); add_edge(r, l);
    }
    for (int i = 1; i <= n; ++i) if (!belong[i]) {
        st = i;
        diameter_length = 0;
        dfs_d(i, -1, ++belong_cnt, 0);
        ed = st;
        st = i;
        diameter_length = 0;
        dfs_d(ed, -1, belong_cnt, 0);
        diameter[belong_cnt] = diameter_length;
        dfs(st, -1, 0);
        dfs(ed, -1, 0);
    }
    for (int i = 1; i <= n; ++i) {
        dis[ belong[i] ].pb(vertice_dis[i]);
    }
    for (int i = 1; i <= belong_cnt; ++i) {
        sort (dis[i].begin(), dis[i].end());
        pre[i].resize(dis[i].size());
        pre[i][0] = dis[i][0];
        for (int j = 1; j < dis[i].size(); ++j) {
            pre[i][j] = pre[i][j - 1] + dis[i][j];
        }
    }
//    for (int i = 1; i <= belong_cnt; ++i) {
//        cout << "now : ";
//        for (int j : dis[i]) cout << j << " "; cout << endl;
//    }
    while (q--) {
        scanf("%d %d", &l, &r);
        l = belong[l]; r = belong[r];
        if (l == r) puts("-1");
        else if (cache.count({l, r})) printf("%.10f\n", cache[{l, r}]);
        else {
            if (dis[l].size() > dis[r].size()) swap(l, r);
            double ans = 0.0;
            int max_diameter = max(diameter[l], diameter[r]);

            for (int i : dis[l]) {
                int pos = upper_bound(dis[r].begin(), dis[r].end(), max_diameter - i - 1) - dis[r].begin();
                if (pos == dis[r].size()) ans += max_diameter * dis[r].size() * 1.0;
                else
                    ans += max_diameter * pos * 1.0 + (i + 1) * (dis[r].size() - pos) + pre[r].back() - (pos == 0 ? 0 : pre[r][pos - 1]);
            }
            ans /= (dis[l].size() * dis[r].size() * 1.0);
            cache[{l, r}] = ans;
            printf("%.10f\n", ans);
        }
    }
    return 0;
}


# include <bits/stdc++.h>
# define pb push_back
# define mp make_pair
# define PII pair<int, int>
# define A first
# define B second
# define LL long long
using namespace std;
const int maxn = 1e5+8;
int n, dis[maxn]={0}, f[maxn]={0}, z[maxn]={0};
vector<int>v[maxn], son[maxn],str[maxn];
vector<LL>pre[maxn];
map<PII, double>M;
PII dfs1(int cur, int pre, int root)
{
    f[cur] = root;
    PII now = mp(0, cur);
    for(auto to : v[cur])
    {
        if(to == pre) continue;
        PII tmp = dfs1(to, cur, root);
        if(tmp.A +1 > now.A) now = mp(tmp.A+1, tmp.B);
    }
    return now;
}
void dfs2(int cur, int pre, int d)
{
    dis[cur] = max(dis[cur], d);
    for(auto to : v[cur])
    {
        if(to == pre) continue;
        dfs2(to, cur, d+1);
    }
}
void init()
{
    for(int i=1; i<=n; ++i)
    {
        if(f[i] == 0)
        {
            PII a = dfs1(i, 0, i);
            PII b = dfs1(a.B, 0, i);
            dfs2(a.B, 0, 0), dfs2(b.B, 0, 0);
            z[i] = b.A;
        }
    }
    for(int i=1; i<=n; ++i) son[f[i]].pb(i);
    for(int i=1; i<=n; ++i)
    {
        if(son[i].size())
        {
            for(auto j : son[i]) str[i].pb(dis[j]);
            sort(str[i].begin(), str[i].end());
            pre[i].pb((LL)str[i][0]);
            for(int j=1; j<str[i].size(); ++j) pre[i].pb(pre[i][j-1]+(LL)str[i][j]);
        }
    }
}
double cal(int a, int b)
{
    if(M.count(mp(a, b))) return M[mp(a,b)];
    double tmp = 0;
    for(auto i : str[a])
    {
        int pos = upper_bound(str[b].begin(), str[b].end(), max(z[a], z[b])-i-1)-str[b].begin();
        if(pos == str[b].size()) tmp += max(z[a], z[b])*1.0*son[b].size();
        else
            tmp += max(z[a], z[b])*1.0*pos + (i+1)*1.0*(son[b].size()-pos)+pre[b].back()-(pos==0?0:pre[b][pos-1]);
    }
    tmp /= (son[a].size()*1.0*son[b].size());
    M[mp(a,b)] = tmp;
    return tmp;
}
int main()
{
    int m, q;
    scanf("%d%d%d",&n,&m,&q);
    while(m--)
    {
        int a, b;
        scanf("%d%d",&a,&b);
        v[a].pb(b), v[b].pb(a);
    }
    init();
    while(q--)
    {
        int a, b;
        scanf("%d%d",&a,&b);
        if(f[a] == f[b]) {puts("-1"); continue;}
        if(son[f[a]].size() > son[f[b]].size()) swap(a, b);
        printf("%.10f\n",cal(f[a], f[b]));
    }
    return 0;
}


/// 求森林间链接一条新的边之后，两棵子树中每个点到树上最远距离的期望
/// 枚举一颗子树的所有点， 如果链接之后整棵树的直径变长 dis[l] + dis[r] + 1 > max(d[l], d[r])
/// 后半部分的期望会改变，以此前缀和二分
/**
 * @Samaritan
 */
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define pb emplace_back
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define PLI pair<LL, int>

LL quick_pow (LL a, LL b, LL mod) {
    LL ans = 1, base = a;
    while (b) {
        if (b & 1) (ans *= base) %= mod;
        b >>= 1;
        (base *= base) %= mod;
    }
    return ans;
}
void gcd(LL a, LL b, LL &d, LL &x, LL &y) {
    if (!b) {
        d = a; x = 1; y = 0;
    } else {
        gcd(b, a % b, d, y, x);
        y -= x * (a / b);
    }
}
LL get_inv(LL a, LL n) {
    LL d, x, y;
    gcd(a, n, d, x, y);
    return d == 1 ? (x + n) % n : -1;
}
inline int log2(const float &x) {
    return ((unsigned &) x >> 23 & 255) - 127;
}
template <typename type>
void show(type arr[], int len) {
    for (int i = 0; i <= len; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
}
const int mod = 1e9 + 7;
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int logN = 20;
const int INF = 1e7;

struct Edge {
    int v, nxt;
} edge[N << 1];
int head[N], edge_cnt;
inline void add_edge(int u, int v) {
    edge[edge_cnt] = {v, head[u]};
    head[u] = edge_cnt++;
}
int belong[N], belong_cnt;
/// 每一个点在自己子树里到最远点的距离
int vertice_dis[N];
/// 每一棵子树里的直径长度
int diameter[N];
/// 每一个子树里的点到最远点的距离，前缀和
vector<int> dis[N];
vector<LL> pre[N];
void init(int n) {
    memset(head, -1, sizeof(head[0]) * (n + 3));
    edge_cnt = 0;
    belong_cnt = 0;
}
/// 搜索直径
int diameter_length, st, ed;
void dfs_d(int now, int par, int belong_id, int dep) {
    belong[now] = belong_id;
    if (dep > diameter_length) {
        diameter_length = dep;
        st = now;
    }
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs_d(to, now, belong_id, dep + 1);
        }
    }
}
void dfs(int now, int par, int dep) {
    vertice_dis[now] = max(vertice_dis[now], dep);
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs(to, now, dep + 1);
        }
    }
}
map<PII, double> cache;

int main() {
    int n, m, q;
    scanf("%d %d %d", &n, &m, &q);
    init(n);
    int l, r;
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &l, &r);
        add_edge(l, r); add_edge(r, l);
    }
    for (int i = 1; i <= n; ++i) if (!belong[i]) {
        st = i;
        diameter_length = 0;
        dfs_d(i, -1, ++belong_cnt, 0);
        ed = st;
        st = i;
        diameter_length = 0;
        dfs_d(ed, -1, belong_cnt, 0);
        diameter[belong_cnt] = diameter_length;
        dfs(st, -1, 0);
        dfs(ed, -1, 0);
    }
    for (int i = 1; i <= n; ++i) {
        dis[ belong[i] ].pb(vertice_dis[i]);
    }
    for (int i = 1; i <= belong_cnt; ++i) {
        sort (dis[i].begin(), dis[i].end());
        pre[i].resize(dis[i].size());
        pre[i][0] = dis[i][0];
        for (int j = 1; j < dis[i].size(); ++j) {
            pre[i][j] = pre[i][j - 1] + dis[i][j];
        }
    }
//    for (int i = 1; i <= belong_cnt; ++i) {
//        cout << "now : ";
//        for (int j : dis[i]) cout << j << " "; cout << endl;
//    }
    while (q--) {
        scanf("%d %d", &l, &r);
        l = belong[l]; r = belong[r];
        if (dis[l].size() > dis[r].size() || (dis[l].size() == dis[r].size() && l > r)) swap(l, r);
        if (l == r) puts("-1");
        else if (cache.count({l, r})) printf("%.10f\n", cache[{l, r}]);
        else {
            double ans = 0.0;
            int max_diameter = max(diameter[l], diameter[r]);

            for (int i : dis[l]) {
                int pos = upper_bound(dis[r].begin(), dis[r].end(), max_diameter - i - 1) - dis[r].begin();
                if (pos == dis[r].size()) ans += max_diameter * dis[r].size() * 1.0;
                else
                    ans += max_diameter * pos * 1.0 + (i + 1) * (dis[r].size() - pos) + pre[r].back() - (pos == 0 ? 0 : pre[r][pos - 1]);
            }
            ans /= (dis[l].size() * dis[r].size() * 1.0);
            cache[{l, r}] = ans;
            printf("%.10f\n", ans);
        }
    }
    return 0;
}


///
/**
 * @Sapicritan
 */
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define pb emplace_back
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define PLI pair<LL, int>

LL quick_pow (LL a, LL b, LL mod) {
    LL ans = 1, base = a;
    while (b) {
        if (b & 1) (ans *= base) %= mod;
        b >>= 1;
        (base *= base) %= mod;
    }
    return ans;
}
void gcd(LL a, LL b, LL &d, LL &x, LL &y) {
    if (!b) {
        d = a; x = 1; y = 0;
    } else {
        gcd(b, a % b, d, y, x);
        y -= x * (a / b);
    }
}
LL get_inv(LL a, LL n) {
    LL d, x, y;
    gcd(a, n, d, x, y);
    return d == 1 ? (x + n) % n : -1;
}
inline int log2(const float &x) {
    return ((unsigned &) x >> 23 & 255) - 127;
}
template <typename type>
void show(type arr[], int len) {
    for (int i = 0; i <= len; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
}
const int mod = 1e9 + 7;
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int logN = 20;
const int INF = 1e7;

struct Edge {
    int v, nxt;
} edge[N << 1];
int head[N], edge_cnt;
inline void add_edge(int u, int v) {
    edge[edge_cnt] = {v, head[u]};
    head[u] = edge_cnt++;
}
int belong[N], belong_cnt;
/// 每一个点在自己子树里到最远点的距离
int vertice_dis[N];
/// 每一棵子树里的直径长度
int diameter[N];
/// 每一个子树里的点到最远点的距离，前缀和
vector<int> dis[N];
vector<int> pre[N];
void init(int n) {
    memset(head, -1, sizeof(head[0]) * (n + 3));
    edge_cnt = 0;
    belong_cnt = 0;
}
/// 搜索直径
int diameter_length, st, ed;
void dfs_d(int now, int par, int belong_id, int dep) {
    belong[now] = belong_id;
    if (dep > diameter_length) {
        diameter_length = dep;
        st = now;
    }
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs_d(to, now, belong_id, dep + 1);
        }
    }
}
void dfs(int now, int par, int dep) {
    vertice_dis[now] = max(vertice_dis[now], dep);
    for (int i = head[now]; ~i; i = edge[i].nxt) {
        int to = edge[i].v;
        if (to != par) {
            dfs(to, now, dep + 1);
        }
    }
}
map<PII, double> cache;

int main() {
    int n, m, q;
    scanf("%d %d %d", &n, &m, &q);
    init(n);
    int l, r;
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &l, &r);
        add_edge(l, r); add_edge(r, l);
    }
    for (int i = 1; i <= n; ++i) if (!belong[i]) {
        st = i;
        dfs_d(i, -1, ++belong_cnt, 0);
        ed = st;
        st = i;
        dfs_d(ed, -1, belong_cnt, 0);
        diameter[belong_cnt] = diameter_length;
        dfs(st, -1, 0);
        dfs(ed, -1, 0);
    }
    for (int i = 1; i <= n; ++i) {
        dis[ belong[i] ].pb(vertice_dis[i]);
    }
    for (int i = 1; i <= belong_cnt; ++i) {
        sort (dis[i].begin(), dis[i].end());
        pre[i].resize(dis[i].size());
        pre[i][0] = dis[i][0];
        for (int j = 1; j < dis[i].size(); ++j) {
            pre[i][j] = pre[i][j - 1] + dis[i][j];
        }
    }
//    for (int i = 1; i <= belong_cnt; ++i) {
//        cout << "now : ";
//        for (int j : dis[i]) cout << j << " "; cout << endl;
//    }
    while (q--) {
        scanf("%d %d", &l, &r);
        l = belong[l]; r = belong[r];
        if (l == r) puts("-1");
        else if (cache.count({l, r})) printf("%.10f\n", cache[{l, r}]);
        else {
            if (dis[l].size() > dis[r].size()) swap(l, r);
            double ans = 0.0;
            int max_diameter = max(diameter[l], diameter[r]);
            for (int i : dis[l]) {
                int pos = upper_bound(dis[r].begin(), dis[r].end(), max_diameter - i - 1) - dis[r].begin();
                if (pos == dis[r].size()) ans += max_diameter * dis[r].size() * 1.0;
                else
                    ans += max_diameter * pos * 1.0 + (i + 1) * (dis[r].size() - pos) + pre[r].back() - (pos == 0 ? 0 : pre[r][pos - 1]);
            }
            ans /= (dis[l].size() * dis[r].size() * 1.0);
            cache[{l, r}] = ans;
            printf("%.10f\n", ans);
        }
    }
    return 0;
}