2 条题解
-
0
可以发现,答案就是路径上可能经过的点数。 考虑将图缩成圆方树,统计树上路径点数。 可以简单发现,如果将方点的权值标为点双大小,圆点的权值标为-1, 则某条路径上可能经过的点数就是圆方树上路径点权和。 直接做是O(n²)的,但是可以改为统计每个点被经过多少次再乘上它的权值,可以利用简单 dfs+dp做到O(n)。
/* 可以发现,答案就是路径上可能经过的点数。 考虑将图缩成圆方树,统计树上路径点数。 可以简单发现,如果将方点的权值标为点双大小,圆点的权值标为-1, 则某条路径上可能经过的点数就是圆方树上路径点权和。 直接做是O(n^2)的,但是可以改为统计每个点被经过多少次再乘上它的权值,可以利用简单 dfs+dp做到O(n)。 */ #include<iostream> #include<bits/stdc++.h> using namespace std; const int N=1e5+10; vector<int>G1[N],G2[N<<1]; int n,m,tsp,cnt,dfn[N],low[N],num,wgh[N<<1],siz[N<<1]; stack<int>stk; long long ans; void tarjan(int x) { dfn[x]=low[x]=++tsp; stk.push(x); ++num; for(int y:G1[x]) { if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); if(dfn[x]==low[y]) { cnt++; wgh[cnt]=0; G2[x].push_back(cnt);++wgh[cnt]; for(int z=-1;z!=y;) { z=stk.top();stk.pop(); G2[cnt].push_back(z);++wgh[cnt]; } } } else low[x]=min(low[x],dfn[y]); } } void dfs(int x) { siz[x]=(x<=n); long long t=0; for(int y:G2[x]) { dfs(y); t+=2ll*siz[x]*siz[y]; siz[x]+=siz[y]; } t+=2ll*siz[x]*(num-siz[x]); ans+=t*wgh[x]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) wgh[i]=-1; for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); G1[x].push_back(y); G1[y].push_back(x); } tsp=0;cnt=n;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low)); ans=0; for(int i=1;i<=n;i++) if(!dfn[i]) { num=0; tarjan(i);stk.pop(); dfs(i); } printf("%lld\n",ans); return 0; } -
0
/* 可以发现,答案就是路径上可能经过的点数。 考虑将图缩成圆方树,统计树上路径点数。 可以简单发现,如果将方点的权值标为点双大小,圆点的权值标为-1, 则某条路径上可能经过的点数就是圆方树上路径点权和。 直接做是O(n^2)的,但是可以改为统计每个点被经过多少次再乘上它的权值,可以利用简单 dfs+dp做到O(n)。 */ #include<bits/stdc++.h> using namespace std; const int N=1e5+10; vector<int>G1[N],G2[N<<1]; int n,m,tsp,cnt,dfn[N],low[N],num,wgh[N<<1],siz[N<<1]; stack<int>stk; long long ans; void tarjan(int x) { dfn[x]=low[x]=++tsp; stk.push(x); ++num; for(int y:G1[x]) { if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); if(dfn[x]==low[y]) { cnt++; wgh[cnt]=0; G2[x].push_back(cnt);++wgh[cnt]; for(int z=-1;z!=y;) { z=stk.top();stk.pop(); G2[cnt].push_back(z);++wgh[cnt]; } } } else low[x]=min(low[x],dfn[y]); } } void dfs(int x) { siz[x]=(x<=n); long long t=0; for(int y:G2[x]) { dfs(y); t+=2ll*siz[x]*siz[y]; siz[x]+=siz[y]; } t+=2ll*siz[x]*(num-siz[x]); ans+=t*wgh[x]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) wgh[i]=-1; for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); G1[x].push_back(y); G1[y].push_back(x); } tsp=0;cnt=n;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low)); ans=0; for(int i=1;i<=n;i++) if(!dfn[i]) { num=0; tarjan(i);stk.pop(); dfs(i); } printf("%lld\n",ans); return 0; }
- 1
信息
- ID
- 2036
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 7
- 标签
- 递交数
- 64
- 已通过
- 16
- 上传者