Map
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 235 Accepted Submission(s): 74
Problem Description
There are N pieces of fragments, and we’re going to select some of them to form a map. Some fragments can be selected into the map directly (named 1-level fragments), while each of the rest follows
exactly one fragment as its prior fragment. If B follows A and A is an i-level fragment, then B is defined as an (i + 1) - level fragment, and B can be selected only if A has been selected before. Besides, a fragment is followed by at most one other fragment.
Each fragment is assigned with a reliability. The reliability of the whole map is sum up by two parts:
1.The sum of reliabilities of all selected fragments;
2.If there are x i i-level fragments in total and we select y i(y i > 1) fragments among them to form the map, the reliability would increase by
,where S
idenotes the sum of reliabilities of selected fragments in level i.
Please figure out the expectation of reliability of the map under the condition that all valid selections are equiprobable.
At least one fragment should be selected.
Each fragment is assigned with a reliability. The reliability of the whole map is sum up by two parts:
1.The sum of reliabilities of all selected fragments;
2.If there are x i i-level fragments in total and we select y i(y i > 1) fragments among them to form the map, the reliability would increase by
![](https://i-blog.csdnimg.cn/blog_migrate/e4f58e76d2840e75a2a9f8af113d2339.jpeg)
Please figure out the expectation of reliability of the map under the condition that all valid selections are equiprobable.
At least one fragment should be selected.
Input
There are several test cases. The number of test cases T (T<=10) occurs in the first line of input.
For each test case:
The first line consists of two integers N, M (1<=N<=10000,0<=M<N), indicating the number of fragments and relationships respectively.
The second line contains N integers, which describes the reliability of each fragment. The given reliability ranges from 1 to 100, inclusive.
Each of the following M lines contains two integers A and B, which denotes
B follows A(0<=A,B<=N-1).
You may assume that the number of 1-level fragments are no more than 10, and levels will not exceed 1000. No fragment will follow itself directly or indirectly.
For each test case:
The first line consists of two integers N, M (1<=N<=10000,0<=M<N), indicating the number of fragments and relationships respectively.
The second line contains N integers, which describes the reliability of each fragment. The given reliability ranges from 1 to 100, inclusive.
Each of the following M lines contains two integers A and B, which denotes
B follows A(0<=A,B<=N-1).
You may assume that the number of 1-level fragments are no more than 10, and levels will not exceed 1000. No fragment will follow itself directly or indirectly.
Output
For each test case, output the expectation with 3 decimal places.
Sample Input
2 2 0 1 2 3 1 1 2 4 1 2
Sample Output
3.000 5.000HintIn the first sample, there’re three ways of selections: {0,1}, {0},{1},which respectively generates 6, 1 and 2 of reliability. Hence, the expectation is 3.
Author
BUPT
这道题目比赛时题意读错了,没看到这句:Besides, a fragment is followed by at most one other fragment.
所以,这题是要求一条条链的和,而不是一棵棵树的和。
因为最多10条链,每条链最多1000层,所以我们可以对每层进行状态压缩求解,复杂度最大为O(1000 * 2 ^10 * 10);
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
#define INF 1e9
#define MAXN 21
const int maxn = 10005;
#define mod 1000000007
#define eps 1e-7
#define pi 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
//ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
bool vis[maxn]; //标记是否为根节点
int f[11][1001]; // f[i][j]表示的是的i棵树的第j层的节点的编号
int son[maxn]; //son[i]表示i的儿子编号
int level[11]; //level[i]表示的是的i棵树一共用几个节点
int val[maxn];
int cnt;
int n,m;
double sum;
void solve()
{
for(int i = 0;i < 1000; i++)
{
int num = 0;
for(int j = 0;j < cnt; j++) if(f[j][i] != -1) num++;
if(num == 0) break;
for(int j = 1;j < (1<<cnt); j++)
{
double s = 0,w = 1;
int y = 0;
for(int k = 0;k < cnt; k++)
{
if(j & (1<<k))
{
if(f[k][i] == -1)
{
s = 0;
break;
}
s += val[f[k][i]]; //s表示当前这层已选点的和
w *= level[k] - i; //表示该种选法这些点会被记录几次
y ++; //当前层已选个数
}
else
{
w *= min(i,level[k]) + 1;
}
}
sum += s * w;
if(y > 1) sum += y * s / num * w;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
while(T--)
{
memset(f,-1,sizeof(f));
ini(level);
memset(son, -1, sizeof(son));
ini(vis);
scan2(n,m);
rep(i,n) scan(val[i]);
int a,b;
rep(i,m)
{
scan2(a,b);
son[a] = b;
vis[b] = 1;
}
cnt = 0;
double ways = 1; //一定要为double型,long long保存不下
for(int i = 0;i < n; i++)
{
if(!vis[i])
{
int k = 0;
for(int j = i;j != -1;j = son[j], k++)
{
f[cnt][k] = j;
}
ways *= k + 1;
level[cnt] = k;
cnt++;
}
}
ways -= 1;
// cout<<ways<<endl;
sum = 0;
solve();
printf("%.3lf\n",sum / ways);
}
return 0;
}