2 条题解
-
0
/*【参考程序】 此题隐含的割点的思想。 siz[x]表示以x为根的搜索树的大小。 删掉的点x后,则增加的不连通有序对数量可分为3部分: 统计原则:独立的点集与“外界点集 ”相乘。 1、若子树y满足dfn[x]<=low[y](子树y独立),则增加Size[y]* (n - siz[y]) 2、点x和外界:1*(n-1) 3、外界 和 x+所有独立搜索树:(n-1-sum)*(sum+1)(sum= ∑(siz[y]),y是独立子树的根节点) */ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+10; vector<pair<int, int>> G[N]; int n, m, tsp, low[N], dfn[N], siz[N]; LL ans[N]; void tarjan(int x, int in_id) { dfn[x] = low[x] = ++tsp; siz[x] = 1; int sum = 0; for(auto i : G[x]) if(i.second != in_id) { int y = i.first, id = i.second; if(dfn[y] == 0) { tarjan(y, id); siz[x] += siz[y]; low[x] = min(low[x], low[y]); if(dfn[x] <= low[y]) { ans[x] += (LL)siz[y] * (n - siz[y]); sum += siz[y]; } } else low[x] = min(low[x], dfn[y]); } ans[x] += n - 1; ans[x] += (LL)(n - 1 - sum) * (sum + 1); } int main() { scanf("%d%d", &n, &m); for(int i=1, x, y; i <= m; i++) { scanf("%d%d", &x, &y); if(x == y) continue; G[x].push_back({y, i}); G[y].push_back({x, i}); } tsp = 0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(ans, 0, sizeof(ans)); memset(siz, 0, sizeof(siz)); for(int i=1; i <= n; i++) if(dfn[i] == 0) tarjan(i, 0); for(int i=1; i <= n; i++) printf("%lld\n", ans[i]); return 0; }/*【参考程序】 此题隐含的割点的思想。 siz[x]表示以x为根的搜索树的大小。 删掉的点x后,则增加的不连通有序对数量可分为3部分: 统计原则:独立的点集与“外界点集 ”相乘。 1、若子树y满足dfn[x]<=low[y](子树y独立),则增加Size[y]* (n - siz[y]) 2、点x和外界:1*(n-1) 3、外界 和 x+所有独立搜索树:(n-1-sum)*(sum+1)(sum= ∑(siz[y]),y是独立子树的根节点) */ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+10; vector<int> G[N]; int n, m, tsp, low[N], dfn[N], siz[N]; LL ans[N]; void tarjan(int x, int fa) { dfn[x] = low[x] = ++tsp; siz[x] = 1; int sum = 0; for(int y : G[x]) if(y != fa) { if(dfn[y] == 0) { tarjan(y, x); siz[x] += siz[y]; low[x] = min(low[x], low[y]); if(dfn[x] <= low[y]) { ans[x] += (LL)siz[y] * (n - siz[y]); sum += siz[y]; } } else low[x] = min(low[x], dfn[y]); } ans[x] += n - 1; ans[x] += (LL)(n - 1 - sum) * (sum + 1); } int main() { scanf("%d%d", &n, &m); for(int i=1, x, y; i <= m; i++) { scanf("%d%d", &x, &y); if(x == y) continue; G[x].push_back(y); G[y].push_back(x); } tsp = 0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(ans, 0, sizeof(ans)); memset(siz, 0, sizeof(siz)); for(int i=1; i <= n; i++) if(dfn[i] == 0) tarjan(i, 0); for(int i=1; i <= n; i++) printf("%lld\n", ans[i]); return 0; } -
0
20241219尝试教的新代码:
/*【参考程序】 此题隐含的割点的思想。 siz[x]表示以x为根的搜索树的大小。 删掉的点x后,则增加的不连通有序对数量可分为3部分: 统计原则:独立的点集与“外界点集 ”相乘。 1、若子树y满足dfn[x]<=low[y](子树y独立),则增加Size[y]* (n - siz[y]) 2、点x和外界:1*(n-1) 3、外界 和 x+所有独立搜索树:(n-1-sum)*(sum+1)(sum= ∑(siz[y]),y是独立子树的根节点) */ #include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+10; vector<pair<int,int>>G[N]; int n,m,tsp,low[N],dfn[N],siz[N]; LL ans[N]; void tarjan(int x,int in_id) { dfn[x]=low[x]=++tsp;siz[x]=1; int sum=0; for(auto i:G[x]) if(i.second!=in_id) { int y=i.first,id=i.second; if(dfn[y]==0) { tarjan(y,id); siz[x]+=siz[y]; low[x]=min(low[x], low[y]); if(dfn[x]<=low[y]) { ans[x]+=(LL)siz[y]*(n-siz[y]); sum+=siz[y]; } } else low[x]=min(low[x], dfn[y]); } ans[x]+=n-1; ans[x]+=(LL)(n-1-sum)*(sum+1); } int main() { scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y);if(x==y)continue; G[x].push_back({y,i}); G[y].push_back({x,i}); } tsp=0;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low)); memset(ans,0,sizeof(ans));memset(siz,0,sizeof(siz)); for(int i=1;i<=n;i++)if(dfn[i]==0)tarjan(i,0); for(int i=1;i<=n;i++)printf("%lld\n",ans[i]); return 0; }
/*【参考程序】 此题隐含的割点的思想。 siz[x]表示以x为根的搜索树的大小。 删掉的点x后,则增加的不连通有序对数量可分为3部分: 统计原则:独立的点集与“外界点集 ”相乘。 1、若子树y满足dfn[x]<=low[y](子树y独立),则增加Size[y]* (n - siz[y]) 2、点x和外界:1*(n-1) 3、外界 和 x+所有独立搜索树:(n-1-sum)*(sum+1)(sum= ∑(siz[y]),y是独立子树的根节点) */ #include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+10; vector<int>G[N]; int n,m,tsp,low[N],dfn[N],siz[N]; LL ans[N]; void tarjan(int x,int fa) { dfn[x]=low[x]=++tsp;siz[x]=1; int sum=0; for(int y:G[x]) if(y!=fa) { if(dfn[y]==0) { tarjan(y,x); siz[x]+=siz[y]; low[x]=min(low[x], low[y]); if(dfn[x]<=low[y]) { ans[x]+=(LL)siz[y]*(n-siz[y]); sum+=siz[y]; } } else low[x]=min(low[x], dfn[y]); } ans[x]+=n-1; ans[x]+=(LL)(n-1-sum)*(sum+1); } int main() { scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y);if(x==y)continue; G[x].push_back(y); G[y].push_back(x); } tsp=0;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low)); memset(ans,0,sizeof(ans));memset(siz,0,sizeof(siz)); for(int i=1;i<=n;i++)if(dfn[i]==0)tarjan(i,0); for(int i=1;i<=n;i++)printf("%lld\n",ans[i]); return 0; }
- 1
信息
- ID
- 2776
- 时间
- 2000ms
- 内存
- 64MiB
- 难度
- 6
- 标签
- 递交数
- 45
- 已通过
- 13
- 上传者