UVA 11600 Masud Rana 并查集+状压概率dp

来源:互联网 发布:app的蜂窝数据打不开 编辑:程序博客网 时间:2024/05/18 02:38

题目链接:点击打开链接

题意:给定一个无向图,给定的边是已经存在的边,每天会任选两个点新建一条边(建过的边还会重建)

问:使得图连通的天数的期望。


思路:状压喽,看别人都是这么写的,n=30,m=0 我也不知道怎么办了。。

当前连通块点数为X 加入一个Y个点的连通块需要的天数为 Y/(n-X);

Masud Rana, A Daring Spy Of Bangladesh Counter Intelligence. He is in a new mission. There is a
total n cities in Bangladesh. Each city is connected to all other by bidirectional roads. So there are
total n ∗ (n − 1)/2 bidirectional roads. Many of the roads are under control of evil powers. City a is
safely reachable from city b, if there is a path from a to b containing only roads which are not under
control of evil powers. There are m roads which are safe from evil powers. The mission of Masud Rana
is to destroy the evil powers of some roads, and make sure that every city is safely reachable from all
other.
Masud Rana chose a new strategy for this special mission. Every morning he selects a random city
other than the city he stays in at that moment, and visit that city by direct connecting road, in the
time of his visit by the road he destroys all evil power of that road if exists any, and makes that road
safe. After reaching new city, he stays there till next morning. In the next morning he checks whether
all cities are safely reachable from all others. If he is already done his mission ends, otherwise he repeats
same strategy.
Let us number the cities by 1, 2, . . . , n. Masud Rana is in city 1 when he starts his mission.
What is the expected number of days to finish the mission for Masud Rana.
Input
Input will starts with an integer T (T ≤ 100) which denotes the number of test case. Each case starts
with two integer N (N ≤ 1 ≤ 30) and M (0 ≤ M ≤ N ∗ (N − 1)/2). Each of the next lines contains
two integers a and b (1 ≤ a, b ≤ N) which means road connecting city a and b is safe.
Output
You have to output the expected number of days required for Masud Rana. Print the case number
followed by the output. Look at the sample in/out for exact format. Upto 1E-6 error in your output
will be acceptable.
Sample Input
2
3 1
2 3
4 1
2 3
Sample Output
Case 1: 1.0
Case 2: 3.5

#include <stdio.h>#include <iostream>#include <algorithm>#include <string.h>#include <queue>#include <map>#include <vector>using namespace std;#define N 35#define M 35*35#define inf 10000000struct Edge{int from, to, next;bool cut;}edge[2 * M];int head[N], edgenum;int n, m;void add(int u, int v){Edge E = { u, v, head[u], 0 }; edge[edgenum] = E; head[u] = edgenum++;Edge E2 = { v, u, head[v], 0 }; edge[edgenum] = E2; head[v] = edgenum++;}int f[N], siz[N];int find(int x){ return x == f[x] ? x : f[x] = find(f[x]); }bool Union(int x, int y){int fx = find(x), fy = find(y);if (fx == fy)return false;if (fx < fy)swap(fx, fy);f[fx] = fy;siz[fy] += siz[fx];return true;}vector<int>A;void suodian(){for (int i = 1; i <= n; i++)f[i] = i, siz[i] = 1;for (int i = 0; i < edgenum; i += 2){int u = edge[i].from, v = edge[i].to;Union(u, v);}for (int i = 1; i <= n; i++)find(i);A.clear();for (int i = 1; i <= n; i++)if (f[i] == i)A.push_back(siz[i]);}void init(){ edgenum = 0; memset(head, -1, sizeof(head)); }map<int, double> dp;int cnt(int x){int ans = 0;for (int i = 0; i < A.size(); i++)if ((1 << i) & x)ans += A[i];return ans;}double dfs(int x){if (dp.count(x))return dp[x];int num = cnt(x);if (num == n)return dp[x] = 0;double ans = (double) (n-1)/(n-num);for (int i = 0; i < A.size(); i++){if (0 == ((1 << i) & x)){ans += dfs((1 << i) ^ x) * A[i] / (n-num);}}return dp[x] = ans;}void input(){init();scanf("%d %d", &n, &m);while (m--){int u, v; scanf("%d %d", &u, &v);add(u, v);}}int main(){int T, Cas = 1; scanf("%d", &T);while (T--){input();suodian();dp.clear();printf("Case %d: %.10f\n", Cas++, dfs(1));}return 0;}


0 0
原创粉丝点击