日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

luogu3244 bzoj4011 HNOI2015 落忆枫音

發(fā)布時間:2024/10/12 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 luogu3244 bzoj4011 HNOI2015 落忆枫音 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這道題目題面真長,廢話一堆。

另外:這大概是我第一道獨立做出來的HNOI2011年以后的題目了吧。像我水平這么差的都能做出來,dalao您不妨試一下自己想想?

?

題目大意:給一個DAG,其中1號點沒有入度,現(xiàn)在新加入一條不重復的邊,使得它可能有環(huán)。求它的生成子圖個數,使得子圖正好包含N-1條邊且1號點與其它的所有點連通。

?

題目分析:

我們首先要發(fā)現(xiàn)這是一個樹的結構!有向的樹。

分析樹的特點,樹的父親只有一個,我們不妨從這里入手。

在這一個生成子圖中,誰是誰的父親?

我們知道1號點一定是root,這是為什么呢?

原因在于一號點沒有入度,我們就認為了它是root。

那么假設有一條x->y的路徑,那么x就是y的父親,這樣的定義是合理的。

?

考慮不加邊之前的情況,圖是一個DAG,我們求它的生成樹(姑且這么叫吧)。

根據我們上面的分析,我們猜想:除一號點外所有點的入度乘積為該圖的生成樹數量。

?

證明如下:

首先我們考慮這個是怎么來的。每個點選擇一個父親,則根據乘法原理得到上面的猜想。

那么我們的命題是:每個點選一個父親,則這個方案必定合法。

我們一共對N-1個點選了到fa的邊,每次選擇都合并了兩個點,共合并了N-1次,因此共N個點被合并,又由于不存在環(huán)的情況,所以這樣的方案是合法的。

?

考慮多了一條邊的情況。那么我們由于已經求得了所有不包含這條邊的情況,我們只需要分析多了這條邊的情況。

假設這是一條從x到y(tǒng)的邊。當這條邊必選的時候,y點必定不被考慮。因為它的父親已經確定。

?

那么我們對剩下的點重新做一遍乘法,得到了ans2。

?

考慮答案多了什么。

?

當選出的邊與當前邊成環(huán)的時候,這個并不是一個生成樹,我們沒辦法解決了嗎?當然不是。

?

我們不妨單獨拿出一個環(huán)考慮。當形成了這個環(huán)的時候,對答案的影響是多少。實際上這不難統(tǒng)計,把剩下的點的入度全部乘起來就是答案。嘿嘿,這不就是總和除以現(xiàn)在的點數嗎。

那么我們考慮求y到x的路徑的點的入度的逆,DP一發(fā)輕松解決。然后乘法分配率證明正確性。

?

后記:這題我先寫了個錯的然后發(fā)現(xiàn)我想錯了,答案小了,調了調變大了,然后又調,結果搜索出了正解233。

?

代碼:

#include<bits/stdc++.h> using namespace std;typedef long long ll;const int maxn = 102000; const int mod = 1000000007; int n,m,x,y; ll ans,ans2; int in[maxn],arr[maxn]; ll dist[maxn],inv[maxn]; vector <int> g[maxn]; vector <int> ng[maxn];ll fast_pow(int now,int p){if(p == 1) return now;if(p == 0) return 1;ll z = fast_pow(now,p/2); z*=z; z %= mod;if(p & 1){z*=now;z%=mod;}return z; }void read(){scanf("%d%d%d%d",&n,&m,&x,&y);for(int i=1;i<=m;i++){int a,b; scanf("%d%d",&a,&b);g[a].push_back(b);in[b]++;ng[b].push_back(a);}for(int i=2;i<=n;i++) inv[i] = fast_pow(in[i],mod-2); }void dfs(int now){if(arr[now]) return;arr[now] = 1;for(int i=0;i<ng[now].size();i++){dfs(ng[now][i]);dist[now] += (dist[ng[now][i]]*inv[now])%mod;dist[now] %= mod;} }void work(){ans = ans2 = 1;for(int i=2;i<=n;i++) ans = (ans*in[i]) % mod;if(x == y){printf("%lld\n",ans);return;}if(y == 1){printf("%lld\n",ans);return;}for(int i=2;i<=n;i++) if(i != y) ans2 = (ans2*in[i]) % mod;in[y]++;inv[y] = fast_pow(in[y],mod-2);dist[y] = inv[y];arr[y] = 1;dfs(x);ans += ans2; ans %= mod;ans -= (ans*dist[x])%mod; ans += mod; ans %= mod;printf("%lld\n",ans); }int main(){read();work();return 0; }

?

轉載于:https://www.cnblogs.com/1-1-1-1/p/8596753.html

總結

以上是生活随笔為你收集整理的luogu3244 bzoj4011 HNOI2015 落忆枫音的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。