hdu4305 Lightning 幾何,生成樹計數

建圖我是用的極角排序,然後枚舉建圖。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<utility>
using namespace std;
const double eps=1e-8;
const double inf=1e10;
const int maxn=305;
const int mod=10007;
struct pos
{
    double first,second;
    int id;
};
int Sign(double x)
{
    return x<-eps?-1:x>eps;
}
double Fabs(double x)
{
    return (Sign(x)<0)?-x:(x>eps?x:0);
}
double multi(pos p0,pos p1,pos p2)
{
    pos v1,v2;
    v1.first=p1.first-p0.first;
    v1.second=p1.second-p0.second;
    v2.first=p2.first-p0.first;
    v2.second=p2.second-p0.second;
    return v1.first*v2.second-v1.second*v2.first;
}
double dist(pos p1,pos p2)
{
    return sqrt(pow(p1.first-p2.first,2)+pow(p1.second-p2.second,2));
}
//*****************************Work*******************
pos p[maxn],tp[maxn];
int Cnt[maxn];
//double C[maxn][maxn];
int C[maxn][maxn];
bool hash[maxn];
bool cmp(pos p1,pos p2)
{
    pos v1,v2;
    double k=multi(p[0],p1,p2);
    if(Sign(k)==-1)
        return 1;
    else if(Sign(k)==0)
    {
        if(Sign(p[0].first-p1.first)==0&&Sign(p[0].first-p2.first)==0)
        {
            if(Sign(p[0].second-p1.second)*Sign(p[0].second-p2.second)<0)
                return Sign(p[0].second-p1.second)>0;
            else
                return dist(p[0],p1)<dist(p[0],p2);
        }
        if(Sign(p[0].first-p1.first)*Sign(p[0].first-p2.first)<0)
        {
            return Sign(p[0].first-p1.first)>0;
        }
        else
        {
            return dist(p[0],p1)<dist(p[0],p2);
        }
    }
    else
        return 0;
}
void swap(int i,int j)
{
    pos tmp;
    tmp=p[j];
    p[j]=p[i];
    p[i]=tmp;
}
int exgcd(int a,int b,int &x,int &y)//乘法逆元返回的d是a,b的公約數,x是a mod b的逆元
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    int d=exgcd(b,a%b,x,y);
    int t=x;
     x=y;
     y=t-a/b*y;
    return d;
}

void Print(int n)
{
    int i,j;
    cout<<"*******************************************"<<endl;
    for(i=0;i<n;++i)
    {
        for(j=0;j<n;++j)
        {
            cout<<" "<<C[i][j];
        }
        cout<<endl;
    }
}
void init(int n,double r)
{
    memset(Cnt,0,sizeof(Cnt));
    memset(C,0,sizeof(C));
    int i,j;
    for(i=0;i<n;++i)
    {
        memcpy(p,tp,sizeof(tp));
        swap(0,i);
        sort(p+1,p+n,cmp);
//        for(j=0;j<n;++j)
//            cout<<'\t'<<p[j].id;
//        cout<<'\t'<<Sign(multi(p[0],p[1],p[2]));
//        cout<<endl;
        for(j=1;j<n;++j)
        {
            if(Sign(dist(p[0],p[j])-r)==1)
                continue;
            if(j>1)
            {
//                cout<<"j==2"<<'\t'<<Sign(multi(p[0],p[j-1],p[j]))<<endl;
//                cout<<Sign(p[0].first-p[j-1].first)<<'\t'<<Sign(p[0].first-p[j].first)<<endl;
                if(Sign(multi(p[0],p[j-1],p[j]))==0)
                {
                    if(Sign(p[0].first-p[j-1].first)==0&&Sign(p[0].first-p[j].first)==0)
                    {
                        if(Sign(p[0].second-p[j-1].second)*Sign(p[0].second-p[j].second)>0)
                        {
//                            cout<<"c1"<<endl;
                            continue;
                        }
                    }
                    else if(Sign(p[0].first-p[j-1].first)*Sign(p[0].first-p[j].first)>0)
                    {
//                        cout<<"c2"<<endl;
                        continue;
                    }
                }
            }
            C[p[0].id][p[j].id]=C[p[j].id][p[0].id]=-1;
            Cnt[p[0].id]++;Cnt[p[j].id]++;
        }
    }
    for(i=0;i<n;++i)
    {
        C[i][i]=Cnt[i]/2;
    }
//    Print(n);
}
void dfs(int u,int n)
{
    hash[u]=true;
    int i,v;
    for(i=0;i<n;++i)
    {
        if(C[u][i]==-1&&!hash[i])
            dfs(i,n);
    }
}
//double Det(int n) //化成下三角形式
//{
//    double ret=1.0,tmp;
//    int i,j,k,sign=0;
//    for(i=0;i<n;++i)
//    {
//        for(j=i;j<n;++j)
//            if(Sign(C[j][i])!=0)
//                break;
//        if(j==n)
//            return 0.0;
//        if(j!=i)
//            sign++;
//        for(k=0;k<n;++k)
//            swap(C[i][k],C[j][k]);
////        Print(n);
//        for(j=i+1;j<n;++j)
//        {
//            tmp=C[i][j]/C[i][i];
//            for(k=i+1;k<n;++k)
//            {
//                C[k][j]-=tmp*C[k][i];
//            }
//        }
////        Print(n);
//    }
//    for(i=0;i<n;++i)
//        ret*=C[i][i];
//    if(sign&1)
//        ret=-ret;
//    return ret;
//}
int det(int n)//計算n階行列式的絕對值 % mod
{
    int ans=1;
    int flag=1;//行列交換的次數
    int i,j,k;
    for(i=0;i<n;i++)
    {
        if(C[i][i]==0)
        {
            for(j=i+1;j<n;j++)
            if(C[j][i])break;
            if(j==n)return 0;//某列的值全是0的ans=0;
            flag=!flag;
            for(int k=i;k<n;k++)
            swap(C[i][k],C[j][k]);//i和j行交換
        }
      ans=ans*C[i][i]%mod;//對角線相乘
      int x,y;
      int tp=exgcd(C[i][i],mod,x,y);//x爲逆元


      for(k=i+1;k<n;k++)
        C[i][k]=C[i][k]*x%mod;


      for(int j=i+1;j<n;j++)
      for(int k=i+1;k<n;k++)
      {
          C[j][k]=(C[j][k]-C[j][i]*C[i][k])%mod;
          if(j==k)
          C[j][k]=(C[j][k]+mod)%mod;
      }
    }


    ans=(ans%mod+mod)%mod;
    if(flag) return ans;
    else  return mod-ans;
}
int main()
{
    int t,n,r,i;
    bool flag;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&r);
        for(i=0;i<n;++i)
        {
            scanf("%lf%lf",&tp[i].first,&tp[i].second);
            tp[i].id=i;
        }
        init(n,r*1.0);
        memset(hash,false,sizeof(hash));
        flag=true;
        dfs(0,n);
        for(i=0;i<n;++i)
            if(hash[i]==false)
                flag=false;
        if(flag)
            printf("%d\n",det(n-1));
        else
            printf("-1\n");
    }
    return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章