Codeforces Round #686 (Div. 3) E. Number of Simple Paths 基环树 + 容斥
生活随笔
收集整理的這篇文章主要介紹了
Codeforces Round #686 (Div. 3) E. Number of Simple Paths 基环树 + 容斥
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
- 題意:
- 思路:
題意:
給你一顆基環樹,求長度>=1>=1>=1的路徑個數。
思路:
先考慮一棵樹,他的答案顯然是n?(n?1)2\frac{n*(n-1)}{2}2n?(n?1)?。因為是個基環樹,所以先考慮如果所有點都在環上,這個時候每兩個點都有兩條路徑可互達,那么答案是n?(n?1)2?2=n?(n?1)\frac{n*(n-1)}{2}*2=n*(n-1)2n?(n?1)??2=n?(n?1)。而現實是我們不可能所有點都在環上,有些點在一棵樹中,這些點對之間只有一條路徑,而剩下兩種情況分別是在環上和在兩棵樹之間,這些顯然還是有兩條路徑可達。那么我們考慮容斥,用總情況減去在一棵樹中的路徑,即n?(n?1)?∑se[i]?(se[i]?1)/2n*(n-1)-\sum se[i]*(se[i]-1)/2n?(n?1)?∑se[i]?(se[i]?1)/2,se[i]se[i]se[i]為每棵樹的大小。用拓撲找出環,讓后跑一遍就好啦。
//#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid (tr[u].l+tr[u].r>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n; int d[N],se[N],st[N]; vector<int>v[N];int dfs(int u,int f) {int ans=1;for(auto x:v[u]) if(x!=f) { ans+=dfs(x,u); }return ans; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);int _; scanf("%d",&_);while(_--){scanf("%d",&n);for(int i=1;i<=n;i++){int a,b; scanf("%d%d",&a,&b);v[a].pb(b); v[b].pb(a);d[a]++; d[b]++;}queue<int>q;for(int i=1;i<=n;i++) if(d[i]==1) q.push(i);while(q.size()){int u=q.front(); q.pop();for(auto x:v[u]) if(--d[x]==1) q.push(x);}for(int i=1;i<=n;i++) if(d[i]>1) st[i]=1;LL ans=1ll*n*(n-1);for(int i=1;i<=n;i++)if(st[i]){LL sum=1;for(auto x:v[i]){if(st[x]) continue;sum+=dfs(x,i);}ans-=sum*(sum-1)/2;}printf("%lld\n",ans);for(int i=1;i<=n;i++) d[i]=0,st[i]=0,se[i]=0,v[i].clear();}return 0; } /**/總結
以上是生活随笔為你收集整理的Codeforces Round #686 (Div. 3) E. Number of Simple Paths 基环树 + 容斥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 家庭路由器哪家强:固件漏洞多年不修复,更
- 下一篇: oracle 查看日志组切换状态_Ora