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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CodeForces - 1551F Equidistant Vertices(暴力+dp)

發布時間:2024/4/11 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1551F Equidistant Vertices(暴力+dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一棵 nnn 個節點組成的樹,問選出 kkk 個節點滿足相互之間距離相等的方案數有多少

題目分析:n=100n=100n=100,感覺數據范圍越小的題目越難發現 tag。補完這個題目后發現每個知識點自己都已經掌握了,但是組合起來就分析不出來,分析題目的能力還是有所欠缺

回到本題,首先特判 k==2k==2k==2 的情況,樣例也給出了提示。

需要思考出的一個思維點就是,kkk 個節點相互之間的距離相等,等價于存在一個中間點 xxx,滿足任意兩個節點 dis(ai,x)=dis(aj,x)dis(a_i,x)=dis(a_j,x)dis(ai?,x)=dis(aj?,x) 成立。所以我們可以去枚舉中間點作為根節點 rootrootroot,然后將 nnn 個節點按照深度分類討論即可。需要注意的是,在同一深度下選出的兩個節點,其路徑必須要經過點 rootrootroot 才有意義,換句話說,必須要保證任意兩個點的 LCA=rootLCA=rootLCA=root 才行。其實處理方法非常簡單,設 sonsonson 集合為 rootrootroot 的相鄰子節點,對于 sonsonson 中每個節點所代表的的子樹中,我們至多選擇一個節點就好啦,稍微轉換一下就是每個子樹至多被選一次,那么這個用 dp[i][j]dp[i][j]dp[i][j] 代表前 iii 個子樹中,選擇了 jjj 個子樹的方案數,用 dp 轉移就好了

至此理論部分結束,時間復雜度是枚舉 rootrootrootO(n)O(n)O(n),枚舉深度的 O(n)O(n)O(n)dpdpdpO(n2)O(n^2)O(n2),共 O(n4)O(n^4)O(n4)

代碼:

// Problem: F. Equidistant Vertices // Contest: Codeforces - Codeforces Round #734 (Div. 3) // URL: https://codeforces.com/contest/1551/problem/F // Memory Limit: 256 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) (x&-x) using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; const int mod=1e9+7; int n,k; vector<int>node[N],son; int cnt[110][110];//cnt[i][j]:第i個子樹深度為j的孩子個數 LL dp[110][110];//dp[i][j]:前i個子樹中選擇了j個子樹的方案數 void dfs(int u,int fa,int root,int deep) {cnt[root][deep]++;for(auto v:node[u]) {if(v==fa) {continue;}dfs(v,u,root,deep+1);} } LL cal(vector<int>son) {memset(dp,0,sizeof(dp));int n=son.size()-1;dp[0][0]=1;for(int i=1;i<=n;i++) {for(int j=0;j<=i;j++) {if(j) {dp[i][j]+=dp[i-1][j-1]*son[i];}dp[i][j]+=dp[i-1][j];dp[i][j]%=mod;}}return dp[n][k]; } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--) {read(n),read(k);for(int i=1;i<=n;i++) {node[i].clear();}for(int i=1;i<n;i++) {int u,v;read(u),read(v);node[u].push_back(v);node[v].push_back(u);}if(k==2) {cout<<n*(n-1)/2<<endl;continue;}LL ans=0;for(int root=1;root<=n;root++) {memset(cnt,0,sizeof(cnt));for(auto v:node[root]) {dfs(v,root,v,1);}for(int dep=1;dep<=n;dep++) {son.clear();son.push_back(-1);//哨兵節點for(auto v:node[root]) {son.push_back(cnt[v][dep]);}ans=(ans+cal(son))%mod;}}cout<<ans<<endl;}return 0; }

總結

以上是生活随笔為你收集整理的CodeForces - 1551F Equidistant Vertices(暴力+dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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