avatar
fireworks99
keep hungry keep foolish

HDU 4305 Lightning(Count spanning trees)

Description

求生成树有几种形状?

Analyze

跟普通生成树计数不同的是,例如一个三角形的图的生成树有三种形状,倘若把这个三角形压成一条线,那生成树就只有一种形状了。

解决办法是:若某两点看似可以连接时,判断一下,若两点连线中间还有点,则这两点不能连线。

Attention

关于取模,含有负数时((x % mod) + mod) % mod,不含有负数时x % mod,倘若有除法取模要用逆元,据说少量逆元可以类似递推出来?

void init()
{
    inv[1]=1;
    for(int i = 2;i < M;i++)
        inv[i] = (M - M / i) * inv[M % i] % M;
}

时间卡的紧:

本来用double的数据迫不得已改用了int

多个判断条件并列时,耗时少的判断放前面

if(A && B && C)
{
    //do something;
}

比如上述代码,A可能只是个普通bool型变量,B可能是一个长长的表达式,C可能是一个循环才能算得出值的bool变量

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define mod int(1e4 + 7)
const int N = 305;

int n, b[N][N], R, x[N], y[N];

double getDis(int u, int v)
{
    return sqrt( (x[u] - x[v])*(x[u] - x[v]) + (y[u] - y[v])*(y[u] - y[v]) );
}

bool sameLine(int a, int b, int c)
{
    bool line = (x[a] - x[b])*(y[b] - y[c]) == (y[a] - y[b])*(x[b]-x[c]);
    bool middle = (x[c] > x[a] && x[c] < x[b]) || (x[c] > x[b] && x[c] < x[a]) ;
    return line && middle;
}



int Gauss()
{
    int res = 1;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            b[i][j] %= mod;
    for(int i = 2; i <= n; ++i)
    {
        for(int j = i + 1; j <= n; ++j)
        {
            while(b[j][i])///turn first not 0 element in row[j] into 0
            {
                int t = b[i][i] / b[j][i];
                for(int k = i; k <= n; ++k)
                    b[i][k] = (b[i][k] - b[j][k] * t) % mod;
                swap(b[i], b[j]);
                res = -res;
            }
        }
        if(b[i][i] == 0)
            return -1;
        res = (res * b[i][i]) % mod;
    }
    return (res + mod) % mod;
}

int main()
{
    int _;
    scanf("%d", &_);
    while(_--)
    {
        scanf("%d %d", &n, &R);
        memset(b, 0,sizeof(b));

        for(int i = 1; i <= n; ++i)
            scanf("%d %d", &x[i], &y[i]);
        for(int i = 1; i <= n; ++i)
            for(int j = i + 1; j <= n; ++j)
            {
                if(!(getDis(i, j) <= R))
                    continue;
                bool flag = 1;
                for(int k = 1; k <= n; ++k)
                    if(k != i && k != j && sameLine(i, j, k))
                    {
                        flag = 0;
                        break;
                    }
                if(flag)
                    b[i][i]++, b[j][j]++, b[i][j] = b[j][i] = -1;
            }
        cout << Gauss() << '\n';
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy