TLE on #25求助
查看原帖
TLE on #25求助
653218
uenohara_ayano楼主2023/3/25 13:38
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,P;
vector<int> ljb[605];
vector<int> G[605];
vector<int> nr;
vector<int> nc;
int cnt;
int rd[605];
int cd[605];
int power(int x,int y=P-2){
    if(y==0)return 1;
    int tmp=power(x,y>>1);
    if(y&1)return tmp*tmp%P*x%P;
    else return tmp*tmp%P;
}
int dp[605][605];
void toposort(){
    queue<int> q;
    for(int i=0;i<nc.size();i++){
        dp[nc[i]][i]=1;
        q.push(nc[i]);
    }
    while(!q.empty()){
        int tmp=q.front();
        q.pop();
        for(int j=0;j<nc.size();j++){
            for(int i=0;i<ljb[tmp].size();i++){
                int v=ljb[tmp][i];
                dp[tmp][j]+=dp[v][j];
                dp[tmp][j]%=P;
            }
        }
        for(int i=0;i<G[tmp].size();i++){
            int v=G[tmp][i];
            cd[v]--;
            if(!cd[v]){
                q.push(v);
            }
        }
    }
    return;
}
int S[605][605];
int solve(int n){
    int ans=1;
    for(int i=0;i<n;i++){
        int maxi=i;
        for(int j=i+1;j<n;j++){
            if(S[j][i]>S[maxi][i])maxi=j;
        }
        if(!S[maxi][i]){
            return 0;
        }
        if(maxi^i)ans=-ans;
        swap(S[maxi],S[i]);
        ans*=S[i][i];
        ans%=P;
        ans+=P;
        ans%=P;
        for(int j=i+1;j<n;j++){
            int dt=S[j][i]*power(S[i][i])%P;
            for(int k=i;k<n;k++){
                S[j][k]-=dt*S[i][k]%P;
                S[j][k]%=P;
                S[j][k]+=P;
                S[j][k]%=P;
            }
        }
    }
    return ans;
}
signed main(){
    scanf("%lld%lld%lld",&n,&m,&P);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%lld%lld",&u,&v);
        ljb[u].push_back(v);
        G[v].push_back(u);
        rd[v]++;
        cd[u]++;
    }
    for(int i=1;i<=n;i++){
        if(rd[i]==0){
            nr.push_back(i);
        }
        if(cd[i]==0){
            nc.push_back(i);
        }
    }
    toposort();
    cnt=nr.size();
    for(int i=0;i<cnt;i++){
        int u=nr[i];
        for(int j=0;j<cnt;j++){
            S[i][j]=dp[u][j];
        }
    }
    //然后算S的行列式
    printf("%lld\n",solve(cnt));
    return 0;
}
/*
对于汇点建反向边。

*/

根据我的计算,她的时间复杂度绝对不会爆炸!

拓扑排序,总共要扫 nn 个点和 mm 条边,每次最多就 n2\frac{n}{2} 个点可能有用,抹去常数就是一个 O(n(n+m))O(n(n+m)) 的算法,为啥会挂掉呢?

2023/3/25 13:38
加载中...