1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| #include<cstdio> #include<cctype> #include<vector> using namespace std; const int N=50000; typedef pair<int,int> pii; int n,m; vector<int>e[N+1]; int cnt; vector<pii>sc[N+1]; long long sum; long long res; int read() { int ret=0; char c=getchar(); while(!isdigit(c)) { c=getchar(); } while(isdigit(c)) { ret=ret*10+c-'0'; c=getchar(); } return ret; } void tarjan(int u,int fa) { static int tot,dfn[N+1],low[N+1],siz[N+1]; static int top; static pii stk[N+1]; dfn[u]=low[u]=++tot,siz[u]=1; for(int v:e[u]) { pii edg=pii{u,v}; if(!dfn[v]) { stk[++top]=edg; tarjan(v,u); low[u]=min(low[u],low[v]); siz[u]+=siz[v]; if(low[v]>dfn[u]) { res+=1ll*siz[v]*(n-siz[v])-1; } if(low[v]>=dfn[u]) { ++cnt; do { sc[cnt].push_back(stk[top]); } while(stk[top--]!=edg); } } else { if((v!=fa)&&(dfn[v]<dfn[u])) { stk[++top]=edg; low[u]=min(low[u],dfn[v]); } } } return; } namespace unionSet { int fa[N+1],siz[N+1]; inline void init() { fill(siz+1,siz+n+1,1); return; } int find(int x) { return fa[x]?fa[x]=find(fa[x]):x; } void merge(int u,int v) { u=find(u),v=find(v); if(u!=v) { fa[v]=u,siz[u]+=siz[v]; } return; } } inline long long calc(int x) { return 1ll*x*(x-1)/2-(x-1); } int main() { n=read(),m=read(); while(m--) { int c=read(),u=read(); while(--c) { int v=read(); e[u].push_back(v),e[v].push_back(u); u=v; } } tarjan(1,0); unionSet::init(); for(int i=1;i<=cnt;++i) { if(sc[i].size()==1) { unionSet::merge(sc[i].front().first,sc[i].front().second); } } for(int i=1;i<=n;++i) { if(!unionSet::fa[i]) { sum+=calc(unionSet::siz[i]); } } for(int i=1;i<=cnt;++i) { if(sc[i].size()==1) { continue; } int s=0; long long tem=sum; for(pii edg:sc[i]) { int u=unionSet::find(edg.first); s+=unionSet::siz[u]; tem-=calc(unionSet::siz[u]); } res+=(tem+calc(s)-1)*sc[i].size(); } printf("%lld\n",res); return 0; }
|