zoukankan      html  css  js  c++  java
  • BZOJ5297 CQOI2018 社交网络

    考前挣扎

    有向图生成树

    我们知道对于无向图生成树可以通过矩阵树定理来算具体就是

    度数矩阵 - 邻接矩阵 去掉任意一行一列得到余子式 对行列式求值

    有向图生成树分为外向和内向两种

    外向生成树当然是所有边指向儿子 他的矩阵树定理是这个样子

    对于有向边(x,y)度数矩阵d[y][y] ++ 邻接矩阵e[x][y] ++

    内向生成树所有边指向父亲

    对于有向边(x,y)度数矩阵d[x][x] ++ 邻接矩阵e[x][y] ++

    (说白了就是外向生成树反过来)

    记忆的一个方法就是度数矩阵只记录入边(就是生成树的入边 【哪里不会点哪里

    然后照常进行度数-邻接 然后我们由于是有向边 那么我们去掉的一行一列(i,i)就表示以i为根

    然后正常行列式求值即可

    (这个题小坑点 边是反着读的= =

    //Love and Freedom.
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf 20021225
    #define ll long long
    #define mdn 10007
    #define N 300
    using namespace std;
    
    int a[N][N],n,m;
    int inv[mdn];
    int gauss()
    {
    	int ans = 1;
    	for(int i=1,j;i<=n;i++)
    	{
    		if(!a[i][i])
    		{
    			for(j=i+1;j<=n;j++)
    				if(a[j][i])	break;
    			if(j>n)	return 0;
    			swap(a[j],a[i]);
    			ans = -ans;
    		}
    		int iv = inv[a[i][i]];
    		for(int j=i+1;j<=n;j++)
    		{
    			int w = iv*a[j][i]% mdn;
    			for(int k=i;k<=n;k++)
    				a[j][k] = (a[j][k]-w*a[i][k]%mdn +mdn)%mdn;
    		}
    	}
    	
    	for(int i=1;i<=n;i++)
    		ans = ans*a[i][i]%mdn;
    	return ans<0?ans+mdn:ans;
    }
    
    int main()
    {
    	int x,y; inv[1] = 1;
    	for(int i=2;i<mdn;i++)
    		inv[i] = (mdn-mdn/i)*inv[mdn%i]%mdn;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		x--; y--;
    		a[x][x]++; a[y][x]--;
    	}
    	n--; printf("%d
    ",gauss());
    	return 0;
    }
  • 相关阅读:
    【HDU1698】 Just a Hook 【线段树入门】
    【转载】线段树 区间合并 小结
    Codeforces 1138B(列方程枚举)
    Codeforces 1132G(关系转化树+dfn+线段树)
    Codeforces 1132E(转化+dp)
    Codeforces 1132D(二分模拟)
    Codeforces 1131G(dp)
    洛谷1941(dp)
    洛谷2758(字符串dp)
    Codeforces 1143B(思维、技巧)
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321869.html
Copyright © 2011-2022 走看看