#include <bits/stdc++.h>
using namespace std;
template <class T>
inline T sqr(T x) {
  return x * x;
}
template <class T>
inline T parse(const string &s) {
  T x;
  stringstream ss(s);
  ss >> x;
  return x;
}
const double EPS = 1e-12;
const int INF = 1000 * 1000 * 1000;
const long long LINF = INF * 1ll * INF;
const double DINF = 1e200;
const double PI = 3.1415926535897932384626433832795l;
int gcd(int a, int b) { return a ? gcd(b % a, a) : b; }
long long gcd(long long a, long long b) { return a ? gcd(b % a, a) : b; }
long long gcdex(long long a, long long b, long long &x, long long &y) {
  if (!a) {
    x = 0, y = 1;
    return b;
  }
  long long k = b / a;
  long long g = gcdex(b - k * a, a, y, x);
  x -= k * y;
  return g;
}
long long inv(long long a, long long m) {
  long long x, y, g;
  g = gcdex(a, m, x, y);
  return (x % (m / g) + m / g) % m / g;
}
long long crt(long long a1, long long m1, long long a2, long long m2) {
  long long a = (a2 - a1 % m2 + m2) % m2;
  long long x, y, g;
  g = gcdex(m1, m2, x, y);
  if (a % g) return -1;
  long long m = m1 / g * m2;
  x *= a / g;
  x = (x % m2 + m2) % m2;
  long long r = (a1 + x * m1) % m;
  assert(r % m1 == a1 && r % m2 == a2);
  return r;
}
long long powmod(long long a, long long p, long long m) {
  long long r = 1;
  while (p) {
    if (p & 1) r = r * a % m;
    p >>= 1;
    a = a * a % m;
  }
  return r;
}
bool isprime(long long a) {
  if (a <= 1) return false;
  for (long long i = 2; i * i <= a; ++i) {
    if (a % i == 0) return false;
  }
  return true;
}
long long sqrtup(long long a) {
  if (!a) return 0;
  long long x = max(0ll, (long long)sqrt((double)a));
  while (x * x >= a) --x;
  while ((x + 1) * (x + 1) < a) ++x;
  return x + 1;
}
long long isqrt(long long a) {
  long long x = max(0ll, (long long)sqrt((double)a));
  while (x * x > a) --x;
  while ((x + 1) * (x + 1) <= a) ++x;
  return x;
}
long long sgn(long long x) { return x < 0 ? -1 : x > 0 ? 1 : 0; }
template <class T>
ostream &operator<<(ostream &s, const vector<T> &v);
template <class A, class B>
ostream &operator<<(ostream &s, const pair<A, B> &p);
template <class K, class V>
ostream &operator<<(ostream &s, const map<K, V> &m);
template <class T, size_t N>
ostream &operator<<(ostream &s, const array<T, N> &a);
template <class... T>
ostream &operator<<(ostream &s, const tuple<T...> &t);
template <class T>
ostream &operator<<(ostream &s, const vector<T> &v) {
  s << '[';
  for (int i = 0; i < (((int)(v).size())); ++i) {
    if (i) s << ',';
    s << v[i];
  }
  s << ']';
  return s;
}
template <class A, class B>
ostream &operator<<(ostream &s, const pair<A, B> &p) {
  s << "(" << p.first << "," << p.second << ")";
  return s;
}
template <class K, class V>
ostream &operator<<(ostream &s, const map<K, V> &m) {
  s << "{";
  bool f = false;
  for (const auto &it : m) {
    if (f) s << ",";
    f = true;
    s << it.first << ": " << it.second;
  }
  s << "}";
  return s;
}
template <class T>
ostream &operator<<(ostream &s, const set<T> &m) {
  s << "{";
  bool f = false;
  for (const auto &it : m) {
    if (f) s << ",";
    f = true;
    s << it;
  }
  s << "}";
  return s;
}
template <class T>
ostream &operator<<(ostream &s, const multiset<T> &m) {
  s << "{";
  bool f = false;
  for (const auto &it : m) {
    if (f) s << ",";
    f = true;
    s << it;
  }
  s << "}";
  return s;
}
template <class T, class V, class C>
ostream &operator<<(ostream &s, const priority_queue<T, V, C> &q) {
  auto a = q;
  s << "{";
  bool f = false;
  while (!a.empty()) {
    if (f) s << ",";
    f = true;
    s << a.top();
    a.pop();
  }
  return s << "}";
}
template <class T, size_t N>
ostream &operator<<(ostream &s, const array<T, N> &a) {
  s << '[';
  for (int i = 0; i < (((int)(a).size())); ++i) {
    if (i) s << ',';
    s << a[i];
  }
  s << ']';
  return s;
}
template <size_t n, class... T>
struct put1 {
  static ostream &put(ostream &s, const tuple<T...> &t) {
    s << get<sizeof...(T) - n>(t);
    if (n > 1) s << ',';
    return put1<n - 1, T...>::put(s, t);
  }
};
template <class... T>
struct put1<0, T...> {
  static ostream &put(ostream &s, const tuple<T...> &t) { return s; }
};
template <class... T>
ostream &operator<<(ostream &s, const tuple<T...> &t) {
  s << "(";
  put1<sizeof...(T), T...>::put(s, t);
  s << ")";
  return s;
}
ostream &put2(ostream &s, const tuple<> &t) { return s; }
template <class U>
ostream &put2(ostream &s, const tuple<U> &t) {
  return s << get<0>(t);
}
template <class U, class V, class... T>
ostream &put2(ostream &s, const tuple<U, V, T...> &t) {
  return s << t;
}
vector<vector<int>> G;
vector<int> D;
vector<int> I;
vector<vector<long long>> S;
vector<vector<long long>> S2;
int dfs1(int v, int pr, int id) {
  I[v] = id;
  int s = 1;
  D[v] = 0;
  for (int p : G[v]) {
    if (p == pr) continue;
    s += dfs1(p, v, id);
    D[v] = max(D[v], D[p] + 1);
  }
  return s;
}
void dfs2(int v, int pr, int u, int id) {
  int a = max(u, D[v]);
  while (((int)(S[id]).size()) <= a + 1) S[id].push_back(0);
  ++S[id][a + 1];
  int mx = 0, mx2 = 0;
  for (int p : G[v]) {
    if (p == pr) continue;
    int d = D[p] + 1;
    if (d > mx) {
      mx2 = mx;
      mx = d;
    } else if (d > mx2) {
      mx2 = d;
    }
  }
  for (int p : G[v]) {
    if (p == pr) continue;
    dfs2(p, v, max(u, D[p] + 1 == mx ? mx2 : mx) + 1, id);
  }
}
int main(int argc, char **argv) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(20);
  int n, m, tc;
  cin >> n >> m >> tc;
  G.resize(n);
  D.resize(n, -1);
  I.resize(n, -1);
  S.resize(n);
  S2.resize(n);
  for (int i = 0; i < (m); ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    G[a].push_back(b);
    G[b].push_back(a);
  }
  for (int i = 0; i < (n); ++i) {
    if (D[i] != -1) continue;
    dfs1(i, -1, i);
    dfs2(i, -1, 0, i);
    S2[i].resize(((int)(S[i]).size()));
    for (int j = 0; j < (((int)(S[i]).size())); ++j)
      S2[i][j] = S[i][j] * (j - 1);
    partial_sum((S[i]).begin(), (S[i]).end(), S[i].begin());
    partial_sum((S2[i]).begin(), (S2[i]).end(), S2[i].begin());
  }
  for (int qqq = 0; qqq < (tc); ++qqq) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    a = I[a];
    b = I[b];
    if (a == b) {
      cout << "-1\n";
      continue;
    }
    if (((int)(S[a]).size()) > ((int)(S[b]).size())) swap(a, b);
    auto &v1 = S[a];
    auto &v2 = S[b];
    do {
    } while (false);
    do {
    } while (false);
    do {
    } while (false);
    long long c = 0;
    double r = 0;
    for (int i = 0; i < (((int)(v1).size()) - 1); ++i) {
      long long t1 = v1[i + 1] - v1[i];
      long long s2 = S2[b].back() - S2[b][((int)(v2).size()) - i - 2] +
                     (i + 1) * (v2.back() - v2[((int)(v2).size()) - i - 2]);
      r += 1. * t1 * s2 +
           1. * (((int)(v2).size()) - 2) * t1 * v2[((int)(v2).size()) - i - 2];
      do {
      } while (false);
    }
    r /= 1. * v1.back() * v2.back();
    cout << r << '\n';
  }
  return 0;
}
