Solution
每两个点都有一条有向边,所以是一个完全有向图。每次走最短的路径,所以是三元环(手玩样例亦可得)。
所以问题就转换为了统计有向图三元环期望个数。考虑转换补集的思想,一共可能有 (inom{n}{3}) 个环,再减去不是环的。发现如果三个点构不成环,那么一定有其中一个点有两条出边。
对于已知的点和边,统计每个点的出度 (d_i),那么一定有 (inom{d_i}{2}) 个三元组构不成环,需减去。(已经可以得 (20) 分了)
现在加入随机边的贡献。每条边的方向是等概率的,对于一个点 (i),它会向其它 (n-1) 个点连边,统计已经确定的且和 (i) 相连的边条数 (s_i),那么剩下的 (n-s_i-1) 条边就有 (2^{n-s_i-1}) 种情况,枚举有其中 (j) 条是 (i) 的出边的情况。这 (j) 条边会和现有的 (d_i) 条出边产生贡献,会造成 (d_i imes j) 个三元组构不成环,概率是 (frac{inom{n-s_i-1}{j}}{2^{n-s_i-1}})。所以要减去
[sum_{j=0}^{n-s_i-1} frac{inom{n-s_i-1}{j}}{2^{n-s_i-1}} imes d_i imes j
]
化简
[frac{d_i}{2^{n-s_i-1}}sum_{j=0}^{n-s_i-1} inom{n-s_i-1}{j} imes j=frac{d_i}{2^{n-s_i-1}}sum_{j=0}^{n-s_i-1} inom{n-s_i-2}{j-1} imes (n-s_i-1)
]
中间再用二项式定理搞掉
[=frac{d_i}{2^{n-s_i-1}} imes 2^{n-s_i-2} imes(n-s_i-1)=frac{d_i(n-s_i-1)}{2}
]
再考虑两条随机边相互之间的贡献。同样枚举个数,有 (j) 条随机边是出边,那么就少 (inom{j}{2}) 个环,加上概率,为
[sum_{j=0}^{n-s_i-1}frac{inom{n-s_i-1}{j}}{2^{n-s_i-1}} imes inom{j}{2}
]
把 (inom{j}{2}) 拆了,用上面相同的方式化简
[frac{n-s_i-1}{2^{n-s_i}}sum_{j=0}^{n-s_i-1} inom{n-s_i-2}{j-1} imes (j-1)=frac{(n-s_i-1)(n-s_i-2)}{2^{n-s_i}}sum_{j=0}^{n-s_i-1} inom{n-s_i-3}{j-2}
]
[=frac{(n-s_i-1)(n-s_i-2)}{2^{n-s_i}} imes 2^{n-s_i-3}=frac{(n-s_i-1)(n-s_i-2)}{8}
]
所以最后要求的值就是
[inom{n}{3}-sum_{i=1}^{n} [inom{d_i}{2}+frac{d_i(n-s_i-1)}{2}+frac{(n-s_i-1)(n-s_i-2)}{8}]
]
#include<stdio.h>
#define Mod 1000000007
#define N 100007
#define ll long long
inline int read(){
int x=0,flag=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return flag? x:-x;
}
ll qpow(ll x,ll y){
ll ret=1,cnt=0;
while(y>=(1LL<<cnt)){
if(y&(1LL<<cnt)) ret=(ret*x)%Mod;
x=(x*x)%Mod,cnt++;
}
return ret;
}
ll n,e;
ll d[N],s[N];
int main(){
freopen("circle.in","r",stdin);
freopen("circle.out","w",stdout);
n=read(),e=read();
for(int i=1;i<=e;i++){
int u=read(),v=read();
d[u]++,s[u]++,s[v]++;
}
ll ans=n*(n-1)%Mod*(n-2)%Mod*qpow(6LL,Mod-2)%Mod;
ll n2=qpow(2LL,Mod-2),n8=qpow(8LL,Mod-2);
for(int i=1;i<=n;i++){
ll ret=d[i]*(d[i]-1)%Mod*n2%Mod;
ret=(ret+d[i]*(n-s[i]-1)%Mod*n2%Mod)%Mod;
ret=(ret+(n-s[i]-1)*(n-s[i]-2+Mod)%Mod*n8%Mod)%Mod;
ans=((ans-ret)%Mod+Mod)%Mod;
}
printf("%lld",ans);
}