点双
void dfs1(int po,int fa){ dfn[po]=low[po]=++cnt; int degcnt=0,flag=0; for (int p=a.nd[po];p!=-1;p=a.next[p]) if (!dfn[a.des[p]]){ degcnt++;sta[++top]=a.id[p]; dfs1(a.des[p],po); low[po]=min(low[po],low[a.des[p]]); if (low[a.des[p]]>=dfn[po]){ flag=1; idcnt++; while (1){ int t=sta[top--]; belo[t]=idcnt; if (t==a.id[p]) break; } } }else{ if (dfn[a.des[p]]<dfn[po]&&a.des[p]!=fa){ low[po]=min(low[po],dfn[a.des[p]]); sta[++top]=a.id[p]; } } if (fa&&flag) bri[po]=1; if ((!fa)&°cnt>=2) bri[po]=1; }
---------------------------------------------------------------------------------------------------
现在有n个通讯基站(从1-n标号),有m对通讯基站之间可以进行直接的互相通讯,保证任意两个通讯基站都能直接或者间接通讯。对于两个不同的通讯基站A和B,如果他们之间的通讯信息必然会经过C(可以为A或者B),那么我们说C是A、B通讯的必经点,显然会有多个必经点。对于任意一个点C可能有多对不同的(A,B)满足C是A、B通讯的必经点。((A,B)和(B,A)只算一对)。
鸡腿的任务是找到一个通讯基站C是最多对通讯基站的通讯必经点。
鸡腿很懒,所以这个任务就交给你了。你需要告诉鸡腿,每一个通讯基站分别是多少对不同的通讯基站的必经点。
建圆方树
#include <cstdio> #include <cstring> #include <iostream> #include <map> #include <utility> #define LL long long using namespace std; struct graph{ int nd[500001],nxt[500001],des[500001],id[500001],cnt; void addedge(int x,int y,int po){ nxt[++cnt]=nd[x];des[cnt]=y;id[cnt]=po;nd[x]=cnt; nxt[++cnt]=nd[y];des[cnt]=x;id[cnt]=po;nd[y]=cnt; } void init(){ memset(nd,-1,sizeof(nd)); } }a,b; map <int,int> mp[500001]; map <pair<int,int> ,int>added; int dfn[500001],low[500001],cnt,sta[500001],top,idcnt,belo[500001]; int n,size[500001],m,sid[500001][2]; LL ans[500001]; void dfs1(int po,int fa){ dfn[po]=low[po]=++cnt; int degcnt=0,flag=0; for (int p=a.nd[po];p!=-1;p=a.nxt[p]) if (!dfn[a.des[p]]){ degcnt++;sta[++top]=a.id[p]; dfs1(a.des[p],po); low[po]=min(low[po],low[a.des[p]]); if (low[a.des[p]]>=dfn[po]){ flag=1; idcnt++; while (1){ int t=sta[top--]; belo[t]=idcnt; if (t==a.id[p]) break; } } }else{ if (dfn[a.des[p]]<dfn[po]&&a.des[p]!=fa){ low[po]=min(low[po],dfn[a.des[p]]); sta[++top]=a.id[p]; } } } void dfs2(int po,int fa){ LL tot=0,sum=0; if (po<=n) sum=1;else sum=0; for (int p=b.nd[po];p!=-1;p=b.nxt[p]) if (b.des[p]!=fa){ dfs2(b.des[p],po); tot+=sum*size[b.des[p]]; sum+=size[b.des[p]]; } size[po]=sum; if (po<=n) ans[po]=tot+sum*(n-sum); } int main(){ scanf("%d%d",&n,&m); a.init();b.init(); for (int i=1;i<=m;i++){ scanf("%d%d",&sid[i][0],&sid[i][1]); if (sid[i][0]>sid[i][1]) swap(sid[i][0],sid[i][1]); if (sid[i][0]==sid[i][1]||added[make_pair(sid[i][0],sid[i][1])]) continue; added[make_pair(sid[i][0],sid[i][1])]=1; a.addedge(sid[i][0],sid[i][1],i); } dfs1(1,0); for (int i=1;i<=m;i++) if (belo[i]){ if (!mp[belo[i]][sid[i][0]]) b.addedge(belo[i]+n,sid[i][0],-1),mp[belo[i]][sid[i][0]]=1; if (!mp[belo[i]][sid[i][1]]) b.addedge(belo[i]+n,sid[i][1],-1),mp[belo[i]][sid[i][1]]=1; } dfs2(1,0); for (int i=1;i<=n;i++) printf("%lld\n",ans[i]); }