1 solutions
-
0
Bitset
可达性用邻接矩阵维护,显然有一个 的做法,但是需要注意常数,本人刚开始无脑每个点算 4 次狠狠 TLE,通过简单整理可以每个点仅算一次。此外,由于
bitest
的count()
复杂度为 ,应该开个数组记录度数代替,不这样做的在洛谷上能通过但本 oj 会 TLE。以下代码可以在此 oj 通过:
using namespace std; typedef long long ll; const int maxn=3e4+2,maxm=3e5+10; int n,m,x[maxm],y[maxm],deg[maxn]; bitset<maxn> b[maxn]; ll ans[7][maxn]; int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n>>m; for(int i=1;i<=m;i++) { cin>>x[i]>>y[i]; b[x[i]][y[i]]=b[y[i]][x[i]]=1; deg[x[i]]++;deg[y[i]]++; } for(int i=1;i<=n;i++) ans[2][i]=m; for(int i=1;i<=m;++i) { int bxby=(b[x[i]]&b[y[i]]).count(); int bxcy=deg[x[i]]-bxby; int bycx=deg[y[i]]-bxby; int cxcy=n-bxby-bxcy-bycx;//(c[x[i]]&c[y[i]]).count(); ans[3][x[i]]+=cxcy;//减去(u,v,u)(u,v,v) ans[3][y[i]]+=cxcy;//减去(u,v,u)(u,v,v) ans[4][x[i]]+=bxcy-1;//减去(u,v,v) ans[4][y[i]]+=bycx-1;//减去(u,v,v) ans[5][x[i]]+=bycx-1;//减去(u,v,v) ans[5][y[i]]+=bxcy-1;//减去(u,v,v) ans[6][x[i]]+=bxby; ans[6][y[i]]+=bxby; ans[2][x[i]]--; ans[2][y[i]]--; } ll tot=1ll*(n-1)*(n-2)/2; for(int i=1;i<=n;i++) { ans[6][i]>>=1;ans[4][i]>>=1; ans[2][i]-=ans[5][i]+ans[6][i]; ans[1][i]=tot-ans[2][i]-ans[3][i]-ans[4][i]-ans[5][i]-ans[6][i]; for(int j=1;j<=6;j++) { ll g=__gcd(ans[j][i],tot); cout<<ans[j][i]/g<<"/"<<tot/g<<" "; } cout<<"\n"; } return 0; }
无向图三元环计数+解方程
于我而言,这就是一道解方程题(大雾)
首先考虑概率如何统计,注意到其他人的分组与自己其实毫无关系,状态空间仅看做从除自己外 个人中选择 个人分组即可。
方便起见,在此规定(与题目规定顺序相同):
: 第 个同学的好友数;
: 3 个学生两两均不为好友;
: 3 个学生中,除自己外的 2 个学生互为好友,不存在其他好友关系;
: 3 个学生中,自己与另外某个学生互为好友,不存在其他好友关系;
: 3 个学生中,恰好有 2 对好友关系,且有 2 个好友的那个人是自己(即:自己与另外 2 个学生分别互为好友,但他们两个不为好友);
: 3 个学生中,恰好有 2 对好友关系,但有 2 个好友的那个人不是自己(即:存在某个学生 A 与自己和另外一个学生 B(分别)互为好友,但自己与 B 不为好友);
: 3 个学生中两两互为好友。
通过观察,我们可以列出如下方程:
情况 2,5,6 枚举了所有不与 相连的边:
枚举所有与 相连的边与任意一个其他点(注意到情况 4,6 具有对称性):
这是总方案数:
情况 4,6 枚举了所有与 相连的边:
情况 5,6 描述了自己认识的人,认识另一人的情形:
$$x_5+x_6=\Sigma_j[e_{jx}==i]deg_{e_{jy}}+\Sigma_j[e_{jy}==i]deg_{e_{jx}}\quad (5) $$个方程 个未知数怎么办呢?我们可以
敏锐地发现情况 6 就是无向图三元环计数, 可以 求出来,那么,问题解决。代码如下:
using namespace std; typedef long long ll; const int maxn=3e5+5; inline int read() { char ch=getchar();bool f=0;int x=0; for(;!isdigit(ch);ch=getchar())if(ch=='-')f=1; for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48); if(f==1)x=-x;return x; } int n,m,u[maxn],v[maxn],deg[maxn],vis[maxn]; vector<int> e[maxn]; ll ans[7][maxn]; int main() { n=read(),m=read(); for(int i=1;i<=m;i++) u[i]=read(),v[i]=read(),deg[u[i]]++,deg[v[i]]++; for(int i=1;i<=m;i++) { if(deg[u[i]]>deg[v[i]]||(deg[u[i]]==deg[v[i]]&&u[i]>v[i])) swap(u[i],v[i]); e[u[i]].push_back(v[i]); ans[5][u[i]]+=deg[v[i]]-1; ans[5][v[i]]+=deg[u[i]]-1; } for(int i=1;i<=n;i++) { for(int j : e[i]) vis[j]=1; for(int j : e[i]) for(int k : e[j]) if(vis[k]) ans[6][i]++,ans[6][j]++,ans[6][k]++; for(int j : e[i]) vis[j]=0; } ll tot=(n-1)*(n-2)/2; for(int i=1;i<=n;i++) { ans[4][i]=1ll*deg[i]*(deg[i]-1)/2-ans[6][i]; ans[5][i]-=ans[6][i]*2; ans[2][i]=m-deg[i]-ans[5][i]-ans[6][i]; ans[3][i]=1ll*deg[i]*(n-2)-2*ans[4][i]-ans[5][i]-2*ans[6][i]; ans[1][i]=tot-ans[2][i]-ans[3][i]-ans[4][i]-ans[5][i]-ans[6][i]; for(int j=1;j<=6;j++) { ll g=__gcd(tot,ans[j][i]); printf("%lld/%lld ",ans[j][i]/g,tot/g); } puts(""); } return 0; }
Information
- ID
- 39
- Time
- 1000ms
- Memory
- 512MiB
- Difficulty
- 7
- Tags
- # Submissions
- 35
- Accepted
- 2
- Uploaded By