『SPOJ 104』(Highways) 生成树计数 Matrix-Tree定理

题目链接:http://www.spoj.com/problems/HIGH/
转载声明:http://blog.csdn.net/jarily/article/details/8901363/

题意:
一个有n座城市的组成国家,城市1至n编号,其中一些城市之间可以修建高速公路;
需要有选择的修建一些高速公路,从而组成一个交通网络;
计算有多少种方案,使得任意两座城市之间恰好只有一条路径;

个人感想:…不会,学习套用,- -我没这种基础知识,看不懂…直接套吧,知道有什么用就差不多了…

代码:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=15;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

 int degree[maxn];
 ll C[maxn][maxn];

 ll det(ll a[][maxn],int n)//生成树计数
 {
     ll ret=1;
     for(int i=1;i<n;i++)
     {
         for(int j=i+1;j<n;j++)
         {
             while(a[j][i])
             {
                 ll t=a[i][i]/a[j][i];
                 for(int k=i;k<n;k++)
                    a[i][k]=(a[i][k]-a[j][k]*t);
                 for(int k=i;k<n;k++)
                    swap(a[i][k],a[j][k]);
                 ret=-ret;
             }
         }
         if(a[i][i]==0)return 0;
         ret=ret*a[i][i];
     }
     if(ret<0)
        ret=-ret;
     return ret;
 }
 int T;
int main()
{

    scanf("%d",&T);
    while(T--)
    {
        memset(degree,0,sizeof(degree));
        memset(C,0,sizeof(C));
        int n,m;
        scanf("%d%d",&n,&m);
        int u,v;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            u--;
            v--;
            C[u][v]=-1;
            C[v][u]=-1;
            degree[u]++;
            degree[v]++;
        }
        for(int i=0;i<n;i++)
            C[i][i]=degree[i];
        printf("%lld\n",det(C,n));
    }

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值