1. 程式人生 > >hackerrank Alex對戰Fedor

hackerrank Alex對戰Fedor

lose read char view 一個 我們 如果 void ems

任意門

為了在漫長得飛行旅途中娛樂,Alex和Fedor發明了如下的一個簡單的雙人遊戲。遊戲是:

  • 首先, Alex畫一個有權無向圖。該圖中可能有多重邊(多重邊的權值可能相同或者不同)。

  • 然後,Fedor選取該圖的一個生成樹。如果該樹是這個圖的最小生成樹,則Fedor獲勝。否則,Alex獲勝。

如果兩棵樹分別包含的邊標號形成的兩個集合不相同,我們認為這兩棵樹不同。兩個集合A和B,如果至少存在一個元素在A中但不在B中,或者反之,至少存在一個元素在B中但不在A中,則我們認為這兩個集合不同。

我們還要指出圖擁有太多的生成樹會讓Alex和Fedor煩亂,於是他們不會用多於$10^{18}$棵生成樹的圖進行遊戲。

現在, Fedor懶得找最小生成樹了,於是他會任選一個Alex的圖的生成樹。每棵生成樹被Fedor選擇的概率相同。請問此時Fedor獲勝的概率是多少?

裸的矩陣樹定理,但是這玩意卡精度,卡了我一個多小時……把long double換成__float128就過了,要是還卡估計就得強行取模+CRT了。

技術分享
#include<cassert>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 401
#define ld __float128
#define ll long long
#define
int long long using namespace std; int read_p,read_ca,read_f; inline int read(){ read_p=0;read_ca=getchar();read_f=1; while(read_ca<0||read_ca>9) read_f=read_ca==-?-1:read_f,read_ca=getchar(); while(read_ca>=0&&read_ca<=9) read_p=read_p*10+read_ca-48,read_ca=getchar();
return read_p*read_f; } struct na{int x,y,z;}b[MN]; bool operator < (na a,na b){return a.z<b.z;} int n,m,a[MN][MN],fa[MN],s[MN]; ll mmh,MMH,o; ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} ld _abs(ld x){return x<0?-x:x;} ll gauss(int n){ static ld b[MN][MN]; int i,j,k; ld x=1; for (i=2;i<=n;i++) for (j=2;j<=n;j++) b[i][j]=a[i][j]; for (i=2;i<=n;i++){ for (j=i;j<=n;j++) if (_abs(b[j][i])>_abs(b[i][i])) for (k=i;k<=n;k++) swap(b[j][k],b[i][k]); for (j=i+1;j<=n;j++){ ld s=b[j][i]; for (k=i;k<=n;k++) b[j][k]-=b[i][k]/b[i][i]*s; } x*=b[i][i]; } return (ll)(_abs(x)+0.5); } int gf(int x){return x==fa[x]?x:fa[x]=gf(fa[x]);} inline void add(int x,int y){x=gf(x);y=gf(y);fa[x]=y;} bool cmp(na a,na b){return gf(a.x)<gf(b.x);} inline ll work(int l,int r){ for (int i=1;i<=n;i++) s[i]=0; for (int i=l;i<r;i++) if (b[i].x!=b[i].y) s[b[i].x]=1,s[b[i].y]=1; for (int i=1;i<=n;i++) s[i]+=s[i-1]; for (int i=1;i<=s[n];i++) for (int j=1;j<=s[n];j++) a[i][j]=0; memset(a,0,sizeof(a)); for (int i=l;i<r;i++) if (b[i].x=s[b[i].x],b[i].y=s[b[i].y],b[i].x!=b[i].y) a[b[i].x][b[i].y]--,a[b[i].y][b[i].x]--,a[b[i].x][b[i].x]++,a[b[i].y][b[i].y]++; return gauss(s[n]); } ll Mavis(){ ll mmh=1; sort(b+1,b+1+m); for (int i=1,j=1;i<=m;i=j){ while (b[j].z==b[i].z&&j<=m) j++; for (int k=i;k<j;k++) b[k].x=gf(b[k].x),b[k].y=gf(b[k].y); for (int k=i;k<j;k++) add(b[k].x,b[k].y); sort(b+i,b+j,cmp); for (int k=i,l=i;k<j;k=l){ while (l<j&&gf(b[l].x)==gf(b[k].x)) l++; mmh*=work(k,l); } } for (int i=2;i<=n;i++) if (gf(i)!=gf(1)) return 0; return mmh; } signed main(){ n=read();m=read(); for (int i=1;i<=n;i++) fa[i]=i; for (int i=1;i<=m;i++) b[i].x=read(),b[i].y=read(),b[i].z=read(), a[b[i].x][b[i].y]--,a[b[i].y][b[i].x]--,a[b[i].x][b[i].x]++,a[b[i].y][b[i].y]++; mmh=gauss(n);MMH=Mavis();o=gcd(mmh,MMH);if (o) mmh/=o,MMH/=o; printf("%lld/%lld\n",MMH,mmh); }
View Code

hackerrank Alex對戰Fedor