#include <bits/stdc++.h>
inline int readChar();
template <class T = int>
inline T readInt();
template <class T>
inline void writeInt(T x, char end = 0);
inline void writeChar(int x);
inline void writeWord(const char* s);
static const int buf_size = 4096;
inline int getChar() {
  static char buf[buf_size];
  static int len = 0, pos = 0;
  if (pos == len) pos = 0, len = fread(buf, 1, buf_size, stdin);
  if (pos == len) return -1;
  return buf[pos++];
}
inline int readChar() {
  int c = getChar();
  while (c <= 32) c = getChar();
  return c;
}
template <class T>
inline T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-') s = -1, c = getChar();
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}
static int write_pos = 0;
static char write_buf[buf_size];
inline void writeChar(int x) {
  if (write_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
  write_buf[write_pos++] = x;
}
template <class T>
inline void writeInt(T x, char end) {
  if (x < 0) writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n) s[n++] = '0' + x % 10, x /= 10;
  while (n--) writeChar(s[n]);
  if (end) writeChar(end);
}
inline void writeWord(const char* s) {
  while (*s) writeChar(*s++);
}
struct Flusher {
  ~Flusher() {
    if (write_pos) fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
  }
} flusher;
using namespace std;
struct static_graph {
  static const int N = 200000;
  static const int M = 300000;
  struct edge {
    int v;
    edge* next;
  } edges[M];
  int nedges;
  struct node {
    int h0, h1, h;
    double m;
    vector<pair<int, int> >* child_sta;
    int comp_mark;
    int dsu_mark;
    int index;
    bool depth_use;
    edge* firstedge;
    inline void init() {
      firstedge = NULL;
      child_sta = new vector<pair<int, int> >();
      depth_use = false;
      h0 = 0;
      h1 = -1;
      comp_mark = -1;
    };
    inline edge* add_edge(edge* e) {
      e->next = firstedge;
      firstedge = e;
      return firstedge;
    };
    inline int getmax(int skipv, int mx) {
      int rez = 0;
      for (int i = 0, count = 0; i < child_sta->size(); i++) {
        if ((*child_sta)[i].second == skipv) continue;
        rez += (*child_sta)[i].first;
        if (++count >= mx) break;
      }
      return rez;
    }
  } nodes[N];
  int nnodes;
  int dsu_get(int v) {
    return (v == nodes[v].dsu_mark)
               ? v
               : (nodes[v].dsu_mark = dsu_get(nodes[v].dsu_mark));
  }
  void dsu_unite(int a, int b) {
    a = dsu_get(a);
    b = dsu_get(b);
    if (rand() & 1) swap(a, b);
    if (a != b) nodes[a].dsu_mark = nodes[b].dsu_mark;
  }
  static_graph() { nnodes = 0, nedges = 0; };
  inline node& new_node() {
    node& r = nodes[nnodes++];
    r.init();
    r.dsu_mark = nnodes - 1;
    r.index = nnodes - 1;
    return r;
  }
  inline edge* new_edge() { return &(edges[nedges++]); };
  inline edge* add_edge(int a, int b) {
    edge* e = new_edge();
    e->v = b;
    return nodes[a].add_edge(e);
  };
  inline void add_bi_edge(int a, int b) {
    add_edge(a, b);
    add_edge(b, a);
    dsu_unite(a, b);
  };
  struct component {
    vector<node*> nodes;
    int maxh;
    vector<int> stats;
    vector<long long int> sums;
  };
  vector<component> comps;
  void build_components() {
    comps.reserve(nnodes);
    for (int i = 0; i < nnodes; i++) {
      node& cur = nodes[i];
      int pid = dsu_get(i);
      if (nodes[pid].comp_mark < 0) {
        component comp;
        nodes[pid].comp_mark = comps.size();
        comps.push_back(comp);
      };
      comps[nodes[pid].comp_mark].nodes.push_back(&cur);
      cur.comp_mark = nodes[pid].comp_mark;
      ;
    };
    for (component& comp : comps) {
      comp.stats.reserve(comp.nodes.size());
      comp.sums.resize(comp.nodes.size() + 1);
      comp.maxh = 0;
      for (node* node : comp.nodes) {
        comp.stats.push_back(node->h);
        comp.maxh = max(comp.maxh, node->h);
      };
      long long int sum = 0;
      sort((comp.stats).begin(), (comp.stats).end());
      ;
      comp.sums[comp.stats.size()] = sum;
      for (int i = comp.stats.size() - 1; i >= 0; i--) {
        sum += comp.stats[i];
        comp.sums[i] = sum;
      };
    };
  }
  component& comp_of(int index) { return comps[nodes[index].comp_mark]; }
  void sortcut(vector<pair<int, int> >& vec, int n) {
    if (vec.size() > n) {
      sort(vec.begin(), vec.end(), greater<pair<int, int> >());
      vec.resize(n);
    };
  }
  void depth_go(int index, int prev, int depth) {
    node& cur = nodes[index];
    if (cur.depth_use++) return;
    node* parent = (prev >= 0) ? &(nodes[prev]) : 0;
    cur.h0 = 0;
    for (edge* e = cur.firstedge; e; e = e->next) {
      if (e->v != prev) {
        node& child = nodes[e->v];
        depth_go(e->v, index, depth + 1);
        cur.h0 = max(cur.h0, 1 + child.h0);
        cur.child_sta->push_back(make_pair(1 + child.h0, e->v));
        sortcut(*cur.child_sta, 2);
      }
    };
  };
  void depth_go2(int index, int prev) {
    node& cur = nodes[index];
    if (cur.depth_use++) return;
    node* parent = (prev >= 0) ? &(nodes[prev]) : 0;
    if (!parent) cur.h1 = 0;
    if (parent) cur.child_sta->push_back(make_pair(cur.h1, prev));
    sort(cur.child_sta->begin(), cur.child_sta->end(),
         std::greater<pair<int, int> >());
    for (edge* e = cur.firstedge; e; e = e->next) {
      node& child = nodes[e->v];
      child.h1 = 1 + cur.getmax(e->v, 1);
      depth_go2(e->v, index);
    };
    cur.h = cur.getmax(-1, 1);
  };
  void depth_run() {
    for (int i = 0; i < nnodes; i++) {
      node& cur = nodes[i];
      cur.depth_use = false;
    };
    for (int i = 0; i < nnodes; i++) {
      node& cur = nodes[i];
      dsu_get(i);
      if (!cur.depth_use) depth_go(i, -1, 0);
    };
    for (int i = 0; i < nnodes; i++) {
      node& cur = nodes[i];
      cur.depth_use = false;
    };
    for (int i = 0; i < nnodes; i++) {
      node& cur = nodes[i];
      if (!cur.depth_use) depth_go2(i, -1);
    };
  };
  void debug() {
    printf("components: \n");
    for (auto c : comps) {
      for (auto x : c.nodes) {
        printf("#%d ", x->index + 1);
      }
      printf("   MAX:%d\n", c.maxh);
    }
    printf("----------------\n");
    for (int i = 0; i < nnodes; i++) {
      node& cur = nodes[i];
      printf("#%d  h=%d  x=%d \n", i + 1, cur.h, dsu_get(i) + 1);
      ;
    }
  }
  double calc(int ia, int ib) {
    if (comp_of(ia).nodes.size() > comp_of(ib).nodes.size()) swap(ia, ib);
    component &a = comp_of(ia), &b = comp_of(ib);
    double sum = 0;
    long long int count = 0;
    int dmax = max(a.maxh, b.maxh);
    for (auto src : a.nodes) {
      int delta = dmax - (src->h + 1);
      int t =
          upper_bound(b.stats.begin(), b.stats.end(), delta) - b.stats.begin();
      sum += (b.sums[t] + (0.0f + b.nodes.size() - t) * (src->h + 1.0f));
      sum += (1.0 * t * dmax);
    }
    return sum / a.nodes.size() / b.nodes.size();
  }
};
static_graph g;
int main() {
  int n, m, q, c, x = 0;
  n = readInt(), m = readInt(), q = readInt();
  for (int i = 0; i < n; i++) {
    static_graph::node& cur = g.new_node();
  };
  for (int i = 0; i < m; i++) {
    int a, b;
    a = readInt(), b = readInt();
    g.add_bi_edge(a - 1, b - 1);
  };
  g.depth_run();
  g.build_components();
  map<pair<int, int>, double> cache;
  for (int i = 0; i < q; i++) {
    int a, b;
    double r = 0;
    a = readInt() - 1, b = readInt() - 1;
    int ia = g.dsu_get(a), ib = g.dsu_get(b);
    if (ia == ib)
      printf("-1\n");
    else {
      if (ia >= ib) swap(ia, ib);
      auto p = make_pair(ia, ib);
      auto it = cache.find(p);
      if (it != cache.end()) {
        r = (*it).second;
      } else {
        r = g.calc(ia, ib);
      }
      cache.emplace(p, r);
      printf("%.10f\n", r);
    }
  };
}
