建立圆方树,考虑所有路径,发现路径上原来的点双(现在的方点)里的点都可以做中间点。但是路径上被方点夹着的圆点被计重了,要扣掉;枚举的两个端点也被算进去了,要扣掉。所以直接将方点权值设为点双大小,圆点权值设为-1,所有圆点间路径权值和的和即为答案
注意图可能不连通,草(汉语)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=200005,M=400005; 7 int n,m,r,c,t1,t2,cnt,Cnt,tot,top; long long sum,ans; 8 int dfn[N],low[N],col[N],isc[N],stk[N],siz[N],dis[N]; 9 int p[N],noww[M],goal[M],P[N],Noww[M],Goal[M],val[N]; 10 vector<int> ve[N]; 11 void Link(int f,int t) 12 { 13 noww[++cnt]=p[f]; 14 goal[cnt]=t,p[f]=cnt; 15 noww[++cnt]=p[t]; 16 goal[cnt]=f,p[t]=cnt; 17 } 18 void Linka(int f,int t) 19 { 20 Noww[++Cnt]=P[f]; 21 Goal[Cnt]=t,P[f]=Cnt; 22 Noww[++Cnt]=P[t]; 23 Goal[Cnt]=f,P[t]=Cnt; 24 } 25 void Tarjan_PBC(int nde) 26 { 27 int tep=0; stk[++top]=nde; 28 dfn[nde]=low[nde]=++tot; 29 for(int i=p[nde];i;i=noww[i]) 30 if(!dfn[goal[i]]) 31 { 32 Tarjan_PBC(goal[i]); 33 low[nde]=min(low[nde],low[goal[i]]); 34 if(dfn[nde]<=low[goal[i]]) 35 { 36 if(nde!=r||++tep>1) isc[nde]=true; 37 int tmp; c++; 38 do 39 { 40 tmp=stk[top--],col[tmp]=c; 41 ve[c].push_back(tmp); 42 }while(tmp!=goal[i]); 43 ve[c].push_back(nde); 44 } 45 } 46 else low[nde]=min(low[nde],dfn[goal[i]]); 47 } 48 void DFS(int nde,int fth) 49 { 50 if(nde<=n) siz[nde]=1; 51 for(int i=P[nde];i;i=Noww[i]) 52 if(Goal[i]!=fth) DFS(Goal[i],nde),siz[nde]+=siz[Goal[i]]; 53 } 54 void Getans(int nde,int fth) 55 { 56 long long tmp=0; 57 int sizz=tot-siz[nde]; 58 for(int i=P[nde];i;i=Noww[i]) 59 if(Goal[i]!=fth) 60 { 61 int G=Goal[i],S=siz[G]; 62 tmp+=1ll*sizz*S,sizz+=S; 63 Getans(Goal[i],nde); 64 } 65 if(nde<=n) ans-=(tmp+tot-1)*2; 66 else ans+=2*tmp*val[nde]; 67 } 68 int main() 69 { 70 scanf("%d%d",&n,&m); 71 for(int i=1;i<=m;i++) 72 scanf("%d%d",&t1,&t2),Link(t1,t2); 73 for(int i=1;i<=n;val[i]=-1,i++) 74 if(!dfn[i]) r=i,Tarjan_PBC(i); 75 for(int i=1;i<=c;i++) 76 { 77 val[n+i]=ve[i].size(); 78 for(int j=0;j<val[n+i];j++) 79 Linka(n+i,ve[i][j]); 80 } 81 for(int i=1;i<=n;i++) 82 if(!siz[i]) DFS(i,0),tot=siz[i],Getans(i,0); 83 printf("%lld",ans); 84 return 0; 85 }