P4455 [CQOI2018]社交网络

传送门

没想到连有向图都有矩阵树……本来还以为是大力容斥……
有向图的矩阵树改一下矩阵的构造,\(G[i][i]\)为点\(i\)的入度,\(G[i][j]\)表示\((i,j)\)之间的边数的相反数,然后求出\((1,1)\)的代数余子式就好了
今天才知道原来模意义下不一定要辗转相除……逆元就行了……而且我以前写的一篇的确有这么写的……
据某大佬说这里只能消掉第一行第一列去求余子式,好像是因为必须得消掉根节点
求余子式的时候忘记变号了……调了半天……

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=255,P=10007;
int n,m,G[N][N],u,v,res;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
int ksm(R int a,R int b){res=1;for(;b;b>>=1,a=a*a%P)if(b&1)res=res*a%P;return res;}
int det(){
    int ans=1,f=1,mx,t,inv;
    fp(i,2,n){
        mx=i;fp(j,i+1,n)if(G[j][i]>G[mx][i])mx=j;
        if(mx!=i){fp(j,i,n)swap(G[i][j],G[mx][j]);f=-f;}
        inv=ksm(G[i][i],P-2);
        fp(j,i+1,n)if(G[j][i]){
            t=G[j][i]*inv%P;
            fp(k,i,n)G[j][k]=dec(G[j][k],G[i][k]*t%P);
        }ans=ans*G[i][i]%P;
    }return add(f*ans,P);
}
int main(){
//  freopen("testdata.in","r",stdin);
    n=read(),m=read();
    fp(i,1,m)v=read(),u=read(),++G[v][v],--G[u][v];
    fp(i,1,n)fp(j,1,n)if(G[i][j]<0)G[i][j]+=P;
    printf("%d\n",det());return 0;
}

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/10084621.html