题目链接

LOJ.

BZOJ.

Solution

先建圆方树。

我们考虑暴力,枚举一个点对,我们枚举的点都是圆点,然后统计中间那个点可以取的位置的数量,加起来就是答案。

那么怎么统计呢,我们对于每个点赋一个点权,方点点权为点双的大小,圆点点权为\(-1\)。

那么这条路径的点权和就是答案,注意要统计到端点的权值。

然后优化就很显然了,直接枚举每个点被算了多少次就行了,这个随便算一下就好了。

复杂度\(O(n)\)。

#include<bits/stdc++.h>
using namespace std; #define int long long void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double
#define ll long long const int maxn = 4e5+10;
const int inf = 1e9;
const lf eps = 1e-8; int cnt,n,m,val[maxn],ans,rt; struct Tree {
int head[maxn],tot,vis[maxn],sz[maxn];
struct edge{int to,nxt;}e[maxn<<1]; void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void ins(int u,int v) {add(u,v),add(v,u);} void dfs(int x,int fa) {
vis[x]=1,sz[x]=x<=n;
for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) dfs(e[i].to,x),sz[x]+=sz[e[i].to];
} void solve(int x,int fa) {
int res=0,s=0;
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa) res+=s*sz[e[i].to],s+=sz[e[i].to];
res+=s*(sz[rt]-sz[x]);res<<=1;ans+=res*val[x];
for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) solve(e[i].to,x);
}
}T; struct Graph {
int head[maxn],tot,dfn[maxn],low[maxn],dfn_cnt,sta[maxn],top;
struct edge{int to,nxt;}e[maxn<<1]; void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void ins(int u,int v) {add(u,v),add(v,u);} void tarjan(int x,int fa) {
dfn[x]=low[x]=++dfn_cnt,sta[++top]=x;
for(int v,i=head[x];i;i=e[i].nxt) {
if((v=e[i].to)==fa) continue;
if(!dfn[v]) tarjan(v,x),low[x]=min(low[x],low[v]);
else {low[x]=min(low[x],dfn[v]);continue;}
if(low[v]>=dfn[x]) {
++cnt;T.ins(cnt,x);val[cnt]++;
while(top) {
int now=sta[top--];T.ins(now,cnt),val[cnt]++;
if(now==v) break;
}
}
}
}
}G; signed main() {
read(n),read(m);for(int i=1,x,y;i<=m;i++) read(x),read(y),G.ins(x,y);
cnt=n;for(int i=1;i<=n;i++) if(!G.dfn[i]) G.tarjan(i,0);
for(int i=1;i<=n;i++) val[i]=-1;
for(int i=1;i<=n;i++) if(!T.vis[i]) rt=i,T.dfs(i,0),T.solve(i,0),ans-=T.sz[i]*(T.sz[i]-1)*2;
write(ans);
return 0;
}

最新文章

  1. 通过配置web.config使WCF向外提供HTTPS的Restful Service
  2. FineReport根据点击次数奇偶性排序之字符型
  3. JavaOne_2016演讲视频:
  4. 一道印象深刻的面试题:String参数传递问题
  5. GPT分区基础知识
  6. Linux centos关机与重启命令详解与实战
  7. emoji处理方法汇总
  8. python高级编程:有用的设计模式2
  9. Aix 光盘软件包安装
  10. 管道是如何处理HTTP请求的?
  11. ConnectivityManager
  12. V8引擎嵌入指南
  13. elasticsearch系列(一) 术语
  14. Python错误集
  15. (数字IC)低功耗设计入门(四)——RTL级低功耗设计
  16. mysql left join
  17. 三种工具绘制errorbar图
  18. django安装及简单使用
  19. 【CH0103】最短哈密顿路径
  20. MySQL--5子查询与连接小结

热门文章

  1. Android:Gradle报错——No resource found that matches the given name (at &#39;dialogCornerRadius&#39; with value &#39;?android:attr/dialogCornerRadius&#39;)
  2. WPF DataGridRow Event
  3. 一些窍门 drawable
  4. hdu1159Common Subsequence(动态规划)
  5. TW实习日记:第20-21天
  6. 376. Binary Tree Path Sum【LintCode java】
  7. 孤荷凌寒自学python第八十一天学习爬取图片1
  8. C二维数组行为空,列不为空
  9. 2.hbase原理(未完待续)
  10. VBA基础之Excel 工作表(Sheet)的操作(二)