• P4455 [CQOI2018]社交网络


    这个题仔细一看就是生成树计数,但是我这个记性是真的差,早就忘了。复习了一下高斯消元,然后这个题就是很裸的题了。

    ps:高斯消元解行列式的时候要取反。

    题干:

    题目背景
    
    当今社会,在社交网络上看朋友的消息已经成为许多人生活的一部分。通常,一个用户在社交网络上发布一条消息(例如微博、状态、Tweet等) 后,他的好友们也可以看见这条消息,并可能转发。转发的消息还可以继续被人转发,进而扩散到整个社交网络中。
    题目描述
    
    在一个实验性的小规模社交网络中我们发现,有时一条热门消息最终会被所有人转发。为了研究这一现象发生的过程,我们希望计算一条消息所有可能的转发途径有多少种。为了编程方便,我们将初始消息发送者编号为1,其他用户编号依次递增。
    
    该社交网络上的所有好友关系是已知的,也就是说对于A、B 两个用户,我们知道A 用户可以看到B 用户发送的消息。注意可能存在单向的好友关系,即lA 能看到B 的消息,但B 不能看到A 的消息。
    
    还有一个假设是,如果某用户看到他的多个好友转发了同一条消息,他只会选择从其中一个转发,最多转发一次消息。从不同好友的转发,被视为不同的情况。
    
    如果用箭头表示好友关系,下图展示了某个社交网络中消息转发的所有可能情况。 (初始消息是用户1发送的,加粗箭头表示一次消息转发)
    
    输入输出格式
    输入格式:
    
    输入文件第一行,为一个正整数n,表示社交网络中的用户数; 第二行为一个正整数m,表示社交网络中的好友关系数目。
    
    接下来m 行,每行为两个空格分隔的整数aia_iai​和bib_ibi​,表示一组好友关系,即用户aia_iai​ 可以看到用户bib_ibi​ 发送的消息。
    
    输出格式:
    
    输出文件共一行,为一条消息所有可能的转发途径的数量, 除以10007 所得的余数。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;++i)
    #define lv(i,a,n) for(register int i = a;i >= n;--i)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int mod = 1e4 + 7;
    int n,m;
    int f[255][255];
    int gauss()
    {
        int ans = 1;
        for(int i = 2;i <= n;++i)
        {
            for(int j = i + 1;j <= n;++j)
            {
                while(f[j][i])
                {
                    int t = f[i][i] / f[j][i];
                    for(int k = i;k <= n;k++)
                    {
                        f[i][k] = (f[i][k] - t * f[j][k] % mod + mod) % mod;
                    }
                    swap(f[i],f[j]);
                    ans = -ans;
                }
            }
            if(f[i][i] == 0) return 0;
            ans = (ans * f[i][i]) % mod;
        }
        return (ans + mod) % mod;
    }
    int main()
    {
        read(n);read(m);
        duke(i,1,m)
        {
            int x,y;
            read(x);read(y);
            f[x][x]++;
            f[x][y]--;
        }
        duke(i,1,n)
        {
            duke(j,1,n)
            {
                if(f[i][j] < 0)
                f[i][j] += mod;
            }
        }
        printf("%d
    ",gauss() % mod);
        return 0;
    }
  • 相关阅读:
    排序
    自动生成存储过程的工具
    感悟javascript
    VS.net 2008 beta2 新功能
    北极光合伙人邓锋:要别人跳火坑,你自己先跳
    [转]驱动开发中应该注意的事项
    [转]CryptoAPI的应用(一)概述以及初始化模块
    [转]强制重启N种法
    Different ways of handling IRPs
    [转]分层驱动模型中IRP的传递与完成
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10507829.html
Copyright © 2020-2023  润新知