码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5080 Colorful Toy(计算几何+polya定理)

时间:2015-09-04 14:18:10      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:

题意:n个点m条边,给边染色,有c种颜色,求染色方案有几种(旋转重合的方案记作同一种);

思路:旋转染色方案数用polya定理解决,每个置换群计算一次;

        由计算几何的方法控制旋转,由sin,cos的有理数性质得,分别计算旋转0,90,180,270的方案数;

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define db double
using namespace std;
const int N=55;
const db eps=1e-8;
const db PI=acos(-1.0);
const ll MOD=1000000007;
int n,m,mp[N][N];
bool mk[N];
ll c;
int sgn(db t){
  return t<-eps?-1:t>eps;
}
ll inv(ll t){   //inv
    ll res=1,k=MOD-2;
    while(k){
      if(k&1) res=(res*t)%MOD;
       t=(t*t)%MOD;
       k>>=1;
    }
    return res;
}
struct E{
  int a,b;
  void input(){
    scanf("%d%d",&a,&b);
  }
}ed[N*N];
struct P{
  db x,y;
  int id;
  void input(){
    int xx,yy;
    scanf("%d%d",&xx,&yy);
    x=xx,y=yy;
  }
  P(db xx=0,db yy=0):x(xx),y(yy){}
  P rot(db thta){ //坐标转化
      return P(x*cos(thta)-y*sin(thta),x*sin(thta)+y*cos(thta)); //不要忘记return!!!
  }
  P rotbyp(P center,db thta){ //绕中心旋转
     P tmp(x-center.x,y-center.y);
     P ans=tmp.rot(thta);
     ans=ans+center;
     return ans;
  }
  P operator + (const P &t)const{
      return P(x+t.x,y+t.y);
  }
  bool operator == (const P &t)const{
     return sgn(x-t.x)==0&&sgn(y-t.y)==0;
  }
}p[N],pb,np[N];
int pt[N];
ll g,ans;
bool check(){
  for(int i=0;i<m;i++){
    int a=ed[i].a,b=ed[i].b; //每条边的两端
    a=pt[a],b=pt[b];
    if(mp[a][b]&&mp[b][a]);  //是否连接
    else return false;
  }
  return true;
}
bool fl[N];
int find_t(){ //不同的等价类的个数,循环节数
  memset(fl,false,sizeof(fl));
  int res=0;
  for(int i=0;i<n;i++){
    if(!fl[i]){
       res++;
    }
    int t=i;
    while(!fl[t]){
        fl[t]=true;
        t=pt[t];
    }
  }
  return res;
}
void dfs(int v){
  if(v==n){ //波利亚计数
    if(check()){
      int t=find_t();
      g++;
      ll res=1;
      for(int i=0;i<t;i++) res=res*c%MOD;
      ans=(ans+res)%MOD;
    }
  }
  else{
      for(int i=0;i<n;i++){
        if(!mk[i]&&(np[v]==p[i])){ //重合点,找到最后一个重合位置
           mk[i]=true;
           pt[v]=i;
           dfs(v+1);
           mk[i]=false;
        }
      }
  }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%I64d",&n,&m,&c);
        pb.x=pb.y=0.0;
        for(int i=0;i<n;i++){
          p[i].input();
          p[i].id=i;
          pb.x+=p[i].x;pb.y+=p[i].y;
        }
        pb.x/=(db)n;pb.y/=(db)n; //中心
        memset(mp,0,sizeof(mp));
        for(int i=0;i<m;i++){
          ed[i].input();
          ed[i].a--;ed[i].b--;
          mp[ed[i].a][ed[i].b]=mp[ed[i].b][ed[i].a]=1;
        } //输入点和边
        ans=g=0;
        memset(mk,false,sizeof(mk));
        for(int i=0;i<4;i++){ //四个角度
          for(int j=0;j<n;j++){
            np[j]=p[j].rotbyp(pb,i*PI/2.0); //旋转后的点
          }
          dfs(0);
        }
        printf("%lld\n",ans*inv(g)%MOD);
    }
    return 0;
}

 

hdu 5080 Colorful Toy(计算几何+polya定理)

标签:

原文地址:http://www.cnblogs.com/dominatingdashuzhilin/p/4781626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!