- 23.44%
- 1000ms
- 262144K
To seek candies for Maomao, Dudu comes to a maze. There are nn rooms numbered from 11 to nn and mm undirected roads.
There are two kinds of rooms in the maze -- candy room and monster room. There is one candy in each candy room, and candy room is safe. Dudu can take the only candy away when entering the room. After he took the candy, this candy room will be empty. A empty room is also safe. If Dudu is in safe, he can choose any one of adjacent rooms to go, whatever it is. Two rooms are adjacent means that at least one road connects the two rooms.
In another kind of rooms, there are fierce monsters. Dudu can't beat these monsters, but he has a magic portal. The portal can show him a randomly chosen road which connects the current room and the other room.
The chosen road is in the map so Dudu know where it leads to. Dudu can leave along the way to the other room, and those monsters will not follow him. He can only use the portal once because the magic energy is not enough.
Dudu can leave the maze whenever he wants. That's to say, if he enters a monster room but he doesn't have enough energy to use the magic portal, he will choose to leave the maze immediately so that he can save the candies he have. If he leave the maze, the maze will never let him in again. If he try to fight with the monsters, he will be thrown out of the maze (never let in, of course). He remembers the map of the maze, and he is a clever guy who can move wisely to maximum the expection of candies he collected.
Maomao wants to know the expected value of candies Dudu will bring back. Please tell her the answer. He will start his adventure in room 1, and the room 1 is always a candy room. Since there may be more than one road connect the current room and the room he wants to go to, he can choose any of the roads.
Input
First line a integer t, means t cases.1≤t≤5
For each case:
First line 3 integer n, m, k, n means the number of rooms, m means the number of roads, k means the number of monster rooms. 1≤n≤100000,n−1≤m≤2∗n, 0≤k≤n
Next m lines, for each line there are two integer aa and b, separated by a space, means there is a road between a and b. There may be repeated edges, but won't be self loop.1≤a,b≤n
In the last line there are kk distinct numbers, the i-th number xi means the number of the i-th monster room is xi, and room 1 won't be monster room. 1≤i≤k
Output
For each case output a real number. The absolute error of the answer should not exceed 10−6.
本题答案不唯一,符合要求的答案均正确
样例输入复制
2
7 6 2
1 2
1 3
2 5
2 4
3 6
4 7
2 3
7 7 2
1 2
1 3
2 5
2 4
3 6
4 7
2 4
2 3
样例输出复制
2.000000
2.250000
题意
杜杜的迷宫里有两种房间,有怪兽的和安全的房间(安全的房间有个糖果),你有一次安全躲过怪兽的机会,躲过怪兽会等概率到达相邻房间,问取得糖果的最大期望
思路
由于只有一个 magic portal,先把当前所在的连通块的糖果全拿走,之
后在第一次遇到敌人的时候使用肯定是最优的。
先用并查集将没有敌人的点合并起来,用一个数组存放该连通块所含点的
数量(称作权值),再用搜索搜出和起点所在连通块相连的怪物点,把这些怪
物点枚举一下,遍历连接这个怪物点的所有边,求边的另一端的连通块的权值
(1 这个点所在连通块的权值要改为 0,因为已经拿过了),求和之后再除以与
该点相连的边数,取最大值,加上 1 所在连通块的权重即可。
因为遇到敌人是随机选择边逃跑,因此遇到重边的时候连通块的权值要累
计多次。同时也是除以连接的边数而不是连接的连通块数量或者房间数量。拿
到的糖果数量至少是 1 所在连通块的权重值,不论经过哪里,都一定能拿到那
些糖果,所以最后答案直接加上即可。
我有点不同的地方,是遍历所有怪物房间(条件1:由房间1可达),找到周围不在房间1所在强连通分量的房间,加上该房间强连通分量的值,然后除以该怪兽房间相连的路径数量,比较得到最大值,就是答案
PS:本以为是水题,补题的时候疯狂WA,不知道为什么,后来才找到存边的数组road容量开小了,我给的容量是点的最大值MAX,但是边的最大容量应该是2*MAX(由题目中m的条件可知),我太粗了。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define rep1(i,s,e) for(int i=s;i<e;i++)
#define rep2(i,s,e,c) for(int i=s;i>=e;i--)
#define pfi(x) printf("%d\n",x)
#define pfl(x) printf("%lld\n",x)
#define pfn() printf("\n")
#define pfs() printf(" ")
#define sfi(x) scanf("%d",&x)
#define sfi1(x,y) scanf("%d%d",&x,&y)
#define sff(x) scanf("%lf",&x)
#define sfl(x) scanf("%lld",&x)
#define memset1(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int MAX = 1e5 + 50;
const int mod = 1e9+7;
int f[MAX],num[MAX];
vector<int> v[MAX];
int find(int x){
if(x!=f[x]) f[x]=find(f[x]);
return f[x];
}
void Union(int a,int b){
int x=find(a);
int y=find(b);
if(x!=y){
f[x]=y;
num[y]+=num[x];
}
}
bool check(int a,int b){
int x=find(a);
int y=find(b);
if(x!=y){
return false;
}
return true;
}
int mst[MAX],road[MAX<<1][2];
bool is_mst[MAX];
void init(int n){
for(int i=0;i<=n;i++){
f[i]=i; num[i]=1;
is_mst[i]=false;
v[i].clear();
}
}
int main(){
int t;
sfi(t);
while(t--){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
init(n);
for(int i=0;i<m;i++){
sfi1(road[i][0],road[i][1]);
v[road[i][0]].push_back(road[i][1]);
v[road[i][1]].push_back(road[i][0]);
}
for(int i=0;i<k;i++){
sfi(mst[i]);
is_mst[mst[i]]=true;
}
for(int i=0;i<m;i++){
if(!is_mst[road[i][0]]&&!is_mst[road[i][1]]){
Union(road[i][0],road[i][1]);
}
}
double ans=0.0;
for(int i=0;i<k;i++){
int len=v[mst[i]].size();
double fz=0.0;
bool flag=false;
for(int j=0;j<len;j++){
if(is_mst[v[mst[i]][j]]) continue;
if(!check(1,v[mst[i]][j])){
fz+=num[find(v[mst[i]][j])];
}
else flag=true;
}
if(!flag) continue;
fz/=len;
ans=max(ans,fz);
}
printf("%.7lf\n",ans+num[find(1)]);
}
return 0;
}
/*
100
8 13 5
1 3
1 2
3 4
4 5
5 2
2 6
1 7
3 8
4 8
5 7
6 7
7 8
6 8
6 7 8 2 3
ans:1.666667
*/