比较裸的多源最短路,或者可以每个点都跑一个Dijkstra。理论上时间过不去,但是pta嘛,典!
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define endl '\n'
#define rep(i,a,n) for (int i = a; i < n; i ++ )
#define repn(i,a,n) for (int i = a; i <= n; i ++ )
#define pb push_back
#define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;
#define all(x) (x).begin(),(x).end()
typedef pair<int,int> PII;
ll lowbit(ll x) { return x & (- x); }
ll gcd(ll a,ll b) { return b ? gcd(b,a % b) : a; }
const int mod = 1e9+7;
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
int n, m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;//头插法
}
void dijkstra(int u)
{
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
dist[u] = 0;//1号点就是起点,距离为0
priority_queue<PII,vector<PII>,greater<PII>> heap;
//为什么要用PII存储呢,因为我们不仅需要知道距离,还需要这个点的编号去更新其他点
heap.push({0, u});//先将起点放进去,first为距离,sec为编号
while(heap.size())
{
auto t = heap.top();//每次取出距离最短的点
heap.pop();
int ver = t.second;
if(st[ver]) continue;//如果已经更新过就不更新了
st[ver] = true;
for(int i = h[ver]; i != -1; i = ne[i] )
{
int j = e[i];//编号
if(dist[j] > dist[ver] + w[i])//如果j这个的距离比当前点距离+到j的距离小;
{
dist[j] = dist[ver] + w[i];
heap.push({dist[j], j});
}
}
}
// if (dist[n] == 0x3f3f3f3f) return -1;
// return dist[n];
}
int main()
{
memset(h, -1, sizeof h);//初始化邻接表的表头
cin >> n >> m;
while (m -- )
{
int a, b;
cin >> a >> b;
add(a, b, 1);//有重边也不要紧,假设1->2有权重为2和3的边,
add(b, a, 1);
//再遍历到点1的时候2号点的距离会更新两次放入堆中,而小根堆顶上是最小值
}
int k;
cin >> k;
while(k -- ) {
int x; cin >> x;
dijkstra(x);
int res = 0;
for (int i = 1; i <= n; i ++ ) res += (i != x ? dist[i] : 0);
cout << "Cc(" << x << ")=";
printf("%.2lf\n", (n - 1 ) * 1.0 / res);
}
return 0;
}