1. 程式人生 > >UVA 12487 Midnight Cowboy(LCA+大YY)(好題)

UVA 12487 Midnight Cowboy(LCA+大YY)(好題)

分配 BE #define second 你會 DC .cn line statistic

題目pdf:http://acm.bnu.edu.cn/v3/external/124/12487.pdf

大致題意:

一棵樹,一個人從A節點出發,等可能的選不論什麽一條邊走,有兩個節點B,C求這個人先到達B的概率


思路:

先說結論:僅僅和離A的距離有關。先到達B+先到達A的概率 = 1,然後依據距離分配一下就好。

構造性證明:假設B-A-C在一條鏈上顯然就是按距離分配概率。由於鏈上的支路對概率一點影響沒有,由於假如走到支路上。你會發現,原本僅僅是向前向後各1/2的概率如今不變成1/3了嗎,並非,一條鏈上的點往C或往B走的概率事實上永遠都是1/2,由於走到支路以後還要考慮這部分最後對概率的貢獻,所以它必定會回到原鏈上。這部分可能性任然會各一半的分流到B或C或其它支路方向,終於等於沒有支路,所以假設B-A-C在一條鏈上顯然就是按距離分配概率


若不在一條鏈上,以A為根,A點始終要到達LCA(B,C) ,如今又變成了一條鏈了,結論仍成立。




標解是,dp[x]是從x點出發先到達B的概率。顯然有dp[B] = 1,dp[C] = 0.

dp[u] = sum(dp[v])/cnt(相鄰的節點數),能夠列線性方程,然後高斯消元解得dp[A]

這樣效率就大大減少了


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
#define rep(i,n) for ( int i=0; i< int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
typedef pair<int,int> pii;
template <class T>
inline bool RD(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != ‘-‘ && (c<‘0‘ || c>‘9‘)) c = getchar();
    sgn = (c == ‘-‘) ?

-1 : 1; ret = (c == ‘-‘) ?

0 : (c - ‘0‘); while (c = getchar(), c >= ‘0‘&&c <= ‘9‘) ret = ret * 10 + (c - ‘0‘); ret *= sgn; return 1; } template <class T> inline void PT(T x) { if (x < 0) { putchar(‘-‘); x = -x; } if (x > 9) PT(x / 10); putchar(x % 10 + ‘0‘); } const int N = 233; int n,A,B,C; vector<int> G[N]; int dep[N]; bool vis[N]; int pa[N][20]; void BFS(int root) { memset(vis,0,sizeof(vis)); dep[root] = 0; queue<int>q; q.push(root); pa[root][0] = root; vis[root] = 1; while(!q.empty()) { int u = q.front(); q.pop(); for(int i=1;i<20;i++) pa[u][i] = pa[pa[u][i-1]][i-1]; foreach(it,G[u]) { int v = *it; if(vis[v] == 0) { vis[v] = 1; pa[v][0] = u; dep[v] = dep[u]+1; q.push(v); } } } } int LCA(int u,int v) { if(dep[u] > dep[v]) swap(u,v); for(int det = dep[v]-dep[u],i = 0;det;i++,det >>= 1) if(det&1) v=pa[v][i]; if(v == u) return v; for(int i = 20-1;i >= 0;i--) if(pa[u][i] != pa[v][i]) v = pa[v][i],u = pa[u][i]; return pa[u][0]; } int main(){ while(scanf("%d%d%d%d",&n,&A,&B,&C) == 4){ REP(i,n) G[i].clear(); REP(i,n-1){ int u,v; RD(u),RD(v); G[u].push_back(v); G[v].push_back(u); } BFS(A); int lca = LCA(B,C); int db = dep[B]-dep[lca]; int dc = dep[C]-dep[lca]; double ans = 0; if( db == 0) ans = 1; else if( dc == 0) ans = 0; else ans = dc/(double)(db+dc); printf("%lf\n",ans); } }







UVA 12487 Midnight Cowboy(LCA+大YY)(好題)