hdu 4921 Map

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 xi i-level fragments in total and we select yi(yi > 1) fragments among them to form the map, the reliability would increase by ,where Sidenotes 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.
 

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.
 

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.000
Hint
In 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;
}



發佈了52 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章