標籤:clear ons 包含 turn math == ret mes getchar
[CC-LONCYC]Lonely Cycles題目大意:
\(T(T\le1000)\)組資料。
給定一張簡單圖(不含重邊與自環),圖中有\(n(n\le2\times10^5)\)個節點和\(m(\sum n+m\le5\times10^6)\)條邊。每個節點最多屬於一個簡單環。
對於每條邊,求出有多少簡單路徑包含這條邊且至多包含一條在簡單環上的邊。
思路:
縮點後根據是否為環上邊討論,環上邊的方案數就是兩邊結點數之積。去掉這些環就只剩下若干棵樹,可以樹形DP。
原始碼:
#include<stack>#include<cstdio>#include<cctype>#include<vector>inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x;}typedef long long int64;const int N=2e5+1,M=5e6;struct Edge2 { int u,v,id;};Edge2 edge[M];struct Edge { int to,id;};std::vector<Edge> e[N];inline void add_edge(const int &u,const int &v,const int &id) { e[u].push_back((Edge){v,id}); e[v].push_back((Edge){u,id});}bool ins[N],vis[N];std::stack<int> s;int dfn[N],low[N],scc[N],size[N],top[N],par[N],sum[N];int64 ans[M];void tarjan(const int &x,const int &par) { s.push(x); ins[x]=true; dfn[x]=low[x]=++dfn[0]; for(auto &j:e[x]) { const int &y=j.to; if(y==par) continue; if(!dfn[y]) { tarjan(y,x); low[x]=std::min(low[x],low[y]); } else if(ins[y]) { low[x]=std::min(low[x],dfn[y]); } } if(dfn[x]==low[x]) { scc[0]++; int y; do { y=s.top(); s.pop(); ins[y]=false; scc[y]=scc[0]; } while(y!=x); }}void dfs(const int &x,const int &par) { ::par[x]=par; size[x]=vis[x]=1; top[x]=par?top[par]:x; for(auto &j:e[x]) { const int &y=j.to; if(y==par||scc[x]==scc[y]) continue; dfs(y,x); size[x]+=size[y]; }}void dp1(const int &x) { for(auto &j:e[x]) { const int &y=j.to; if(y==par[x]||top[x]!=top[y]) continue; dp1(y); sum[x]+=sum[y]; }}void dp2(const int &x) { for(auto &j:e[x]) { const int &y=j.to,&id=j.id; if(y==par[x]||top[x]!=top[y]) continue; dp2(y); ans[id]+=(int64)(size[top[x]]-size[y])*size[y]; ans[id]+=(int64)(sum[top[x]]-sum[y])*size[y]; ans[id]+=(int64)sum[y]*(size[top[x]]-size[y]); }}int main() { for(register int T=getint();T;T--) { const int n=getint(),m=getint(); for(register int i=0;i<m;i++) { edge[i].u=getint(); edge[i].v=getint(); edge[i].id=i; add_edge(edge[i].u,edge[i].v,i); } for(register int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i,0); } for(register int i=1;i<=n;i++) { if(!vis[i]) dfs(i,0); } for(register int i=0;i<m;i++) { const int &u=edge[i].u,&v=edge[i].v; if(scc[u]!=scc[v]) continue; ans[i]=(int64)size[top[u]]*size[top[v]]; sum[u]+=size[top[v]]; sum[v]+=size[top[u]]; } for(register int i=1;i<=n;i++) { if(i==top[i]) dp1(i); } for(register int i=1;i<=n;i++) { if(i==top[i]) dp2(i); } for(register int i=0;i<m;i++) { printf("%lld\n",ans[i]); } //Reset for(register int i=1;i<=n;i++) { e[i].clear(); } std::fill(&sum[1],&sum[n]+1,0); std::fill(&dfn[0],&dfn[n]+1,0); std::fill(&ans[0],&ans[m],0); std::fill(&vis[1],&vis[n]+1,false); scc[0]=0; } return 0;}
[CC-LONCYC]Lonely Cycles