• Codeforces Round #114 (Div. 1) E Wizards and Bets


    题目链接:Wizards and Bets

    这场CF的D题感觉读不懂,而且过题人数比E题少很多,所以就看的E题了。

    题意:一个有向图中,没有出度的边称为 sink,没有入度的边称为 source,且保证其数目相等,并对其按照大小排序分别得到了新的顺序。现在要求 source 中的点与 sink 中的点一一对应,且路径中不存在相交的地方,对于 source 中的两个点 (i, j) ,对应 sink 中的点分别为 (x1, x2),若是序列的逆序数为偶数则得分为 +1,否则为 -1。问所有的不存在相交的边的情况中,可以得到的总分是多少。

    题解:刚刚考完研,居然就忘了行列式与逆序数之间的关系。对于相交的边,总存在与其对称的情况把其抵消掉,所以这个情况可以不用考虑,直接计算总的情况即可。定义矩阵 matrix[i][j] 为 source 中的点 i 到 sink 中的点 j 的不同路径数,然后对求这个矩阵的行列式即可。

       其中计算行列式为高斯消元,然后对角线元素相乘,抄了个板子贴了上来。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    
    vector<int> g[1005];
    LL n,m,p;
    LL in[1005],out[1005],pos1[1005],pos2[1005],cnt1,cnt2;
    LL matrix[1005][1005],num[1005][1005];
    LL vis[1005];
    LL sink[1005],sink_num,source[1005],source_num;
    
    void dfs(LL u){
        vis[u]=1;
        if(out[u]==0){
            num[u][u]=1;
        }
        for(LL i=0;i<g[u].size();i++){
            LL v=g[u][i];
            if(!vis[v]) dfs(v);
            for(LL j=0;j<sink_num;j++){
                num[u][sink[j]]=(num[v][sink[j]]+num[u][sink[j]])%p;
            }
        }
    }
    
    void solve(LL n){
        LL ans=1,flag=0;
        for(LL i=0;i<n;i++){
            for(LL j=i+1;j<n;j++){
                LL x=i,y=j;
                while(matrix[y][i]){
                    LL t=matrix[x][i]/matrix[y][i];
                    for(LL k=i;k<n;k++) matrix[x][k]=(matrix[x][k]-matrix[y][k]*t)%p;
                    swap(x,y);
                }
                if(x!=i){
                    for(LL k=0;k<n;k++) swap(matrix[i][k],matrix[x][k]);
                    flag^=1;
                }
            }
            if(matrix[i][i]==0){
                printf("%d
    ",0);
                return ;
            }
            else ans=ans*matrix[i][i]%p;
        }
    
        if(flag!=0) ans*=-1;
        if(ans<0) ans+=p;
        printf("%lld
    ",ans);
    }
    
    int main(){
        scanf("%lld%lld%lld",&n,&m,&p);
        for(LL i=1;i<=m;i++){
            LL u,v;
            scanf("%lld%lld",&u,&v);
            out[u-1]++;
            in[v-1]++;
            g[u-1].push_back(v-1);
        }
        for(LL i=0;i<n;i++){
            if(in[i]==0){
                pos1[i]=cnt1++;
                source[source_num++]=i;
            }
            if(out[i]==0){
                pos2[i]=cnt2++;
                sink[sink_num++]=i;
            }
        }
        for(LL i=0;i<n;i++) if(in[i]==0) dfs(i);
        for(LL i=0;i<cnt1;i++){
            for(LL j=0;j<cnt2;j++){
                matrix[i][j]=num[source[i]][sink[j]];
            }
        }
        solve(cnt1);
    
    
        return 0;
    }
  • 相关阅读:
    iOS 代码规范
    Clang Format
    PullToRefreshListView手动刷新问题
    android不依赖具体activity弹出Dialog对话框,即全局性对话框
    我的手机华为荣耀7,运行android程序不输出Log
    Android从imageview中获得bitmap
    Fragment里面的ViewPager嵌套subFragment,主Fragment切换的时候subFragment出现空白Fragment的Bug
    解决某些手机RadioGroup中的RadioButton不居中的问题
    Android权限大全
    UML类图
  • 原文地址:https://www.cnblogs.com/N-Psong/p/10281725.html
Copyright © 2020-2023  润新知