zoukankan      html  css  js  c++  java
  • 19_04_02校内训练[图染色]

    题意

    给一个联通无向图,有n个点和m条边,要求用k种颜色为其染色,使得相邻的两个点颜色不同。n-m≤5,n、m≤100,000。k很大。


    思考

    若n、m≤8,用最小表示(例如,染色[1,5,3,1]<=>[1,3,2,1])。对于一种染色的最小表示,若使用了m种不同的颜色,最后的结果乘以k!/(k-m)!即可。

    考虑到边数与点数的差很小,尝试将原图缩小。

    第一种点:度数为1。此时可以直接删除,最后答案乘以k-1。

    第二种点:度数为2。此时可以将与它相邻的两个点连起来,并附上新的边权。最后对于一种暴力的染色方案,相应的边乘以相应的边权即可。

    这样边权就分为两种,一种是两端点颜色不同,一种是两端点颜色相同。我们又知道,对于长度相同的链,无论在哪,最后缩成一条边的贡献一定是一样的。

    设type0[i]表示两端点颜色不同,这条边上有i-1个点(为什么i-1,因为方便边权相加)不同的方案数,type1[i]表示两端点颜色相同,i-1个点不同的方案数。

    type0[i]=type1[i-1]+type0[i-1]*(k-2)

    type1[i]=type1[i-1]*(k-2)+type1[i-2]*(k-1)

    初始值

    type0[1]=1
    type0[2]=k-2
    type1[2]=k-1

    缩完边后暴力统计答案。

    O(nm3n),这里n≤10,m≤15。


    在脑抽情况下写出的代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long int ll;
      4 const ll maxn=1E5+15;
      5 const ll mod=1E9+7;
      6 ll n,m,k,type0[maxn],type1[maxn],x,y,in[maxn],gg=1,cur,c[maxn],top,back[maxn],ti,ans,what[maxn],vis[maxn];
      7 ll flag;
      8 ll inv[maxn];
      9 vector<int>E[maxn];
     10 map<pair<int,int>,int>w;
     11 pair<int,int> M(int x,int y)
     12 {
     13     if(x>y)swap(x,y);
     14     return make_pair(x,y);
     15 }
     16 void erase(vector<int>&S,int x)
     17 {
     18     for(vector<int>::iterator pt=S.begin();;++pt)
     19         if(*pt==x){S.erase(pt);break;}
     20 }
     21 void add(int u,int v)
     22 {
     23     E[u].push_back(v);
     24     E[v].push_back(u);
     25     w[M(u,v)]=1;
     26 }
     27 void merge(int x,int u,int v)
     28 {
     29     erase(E[u],x);
     30     erase(E[v],x);
     31     erase(E[x],u);
     32     erase(E[x],v);
     33     add(u,v);
     34     ll g1=w[M(u,x)],g2=w[M(x,v)];
     35     w[M(u,x)]=w[M(x,v)]=0;
     36     w[M(u,v)]=g1+g2;
     37     in[x]=0;
     38     --cur;
     39 }
     40 void dfs1(int u)
     41 {
     42     vis[u]=flag;
     43     for(int i=0;i<E[u].size();++i)
     44     {
     45         int v=E[u][i];
     46         if(vis[v]==flag)continue;
     47         dfs1(v);
     48         if(in[v]==1)
     49         {
     50             erase(E[u],v);
     51             erase(E[v],u);
     52             --in[v],--in[u];
     53             gg=gg*(k-1)%mod;
     54             --cur;
     55         }
     56     }
     57 }
     58 void paint(int u)
     59 {
     60     back[u]=++ti;
     61     what[ti]=u;
     62     vis[u]=1;
     63     for(int i=0;i<E[u].size();++i)
     64     {
     65         int v=E[u][i];
     66         if(vis[v])continue;
     67         paint(v);
     68     }
     69 }
     70 ll qpow(ll x,ll y)
     71 {
     72     ll ans=1,base=x;
     73     while(y)
     74     {
     75         if(y&1)ans=ans*base%mod;
     76         base=base*base%mod;
     77         y>>=1;
     78     }
     79     return ans;
     80 }
     81 void get()
     82 {
     83     ll sum=gg;
     84     for(int u=1;u<=cur;++u)
     85     {
     86         for(int i=0;i<E[what[u]].size();++i)
     87         {
     88             int v=E[what[u]][i];
     89             if(u>back[v])continue;
     90             if(c[u]==c[back[v]])sum=sum*type1[w[M(what[u],v)]]%mod;
     91             else sum=sum*type0[w[M(what[u],v)]]%mod;
     92         }
     93     }
     94     sum=sum*inv[k]%mod*qpow(inv[k-top],mod-2)%mod;
     95     ans=(ans+sum)%mod;
     96 }
     97 void dfs(int s)
     98 {
     99     if(s==cur+1){get();return;}
    100     for(int i=1;i<=top;++i)
    101     {
    102         c[s]=i;
    103         for(int j=0;j<E[what[s]].size();++j)
    104         {
    105             int v=E[what[s]][j];
    106             if(back[v]>=s)continue;
    107             if(c[s]==c[back[v]]&&type1[w[M(what[s],v)]]==0)goto end;
    108             else if(type0[w[M(what[s],v)]]==0)goto end;
    109         }
    110         dfs(s+1);
    111         end:;
    112     }
    113     ++top;
    114     c[s]=top;
    115     dfs(s+1);
    116     --top;
    117 }
    118 void init()
    119 {
    120     type0[1]=1;
    121     type0[2]=k-2;
    122     type1[2]=k-1;
    123     for(int i=3;i<=n;++i)
    124     {
    125         type0[i]=(type1[i-1]%mod+type0[i-1]*(k-2)%mod)%mod;
    126         type1[i]=(type1[i-1]*(k-2)%mod+type1[i-2]*(k-1)%mod)%mod;
    127     }
    128     inv[0]=1;
    129     for(int i=1;i<=k;++i)inv[i]=inv[i-1]*i%mod;
    130 }
    131 int main()
    132 {
    133     freopen("7_1.in","r",stdin);
    134     ios::sync_with_stdio(false);
    135     cin>>n>>m>>k;
    136     init();
    137     for(int i=1;i<=m;++i)
    138     {
    139         cin>>x>>y;
    140         add(x,y);
    141         ++in[x],++in[y];
    142     }
    143     cur=n;
    144     for(int i=1;i<=n;++i)if(in[i]==1){++flag;dfs1(i);}
    145     memset(vis,0,sizeof(vis));
    146     for(int i=1;i<=n&&cur>3;++i)
    147         if(in[i]==2&&w[M(E[i][0],E[i][1])]==0)merge(i,E[i][0],E[i][1]);
    148     for(int i=1;i<=n;++i)
    149     {
    150         if(E[i].size()!=0)
    151         {
    152             paint(i);
    153             break;
    154         }
    155     }
    156     dfs(1);
    157     cout<<ans<<endl;
    158     return 0;
    159 }
    View Code
  • 相关阅读:
    c# linq查询的等于大于符号是什么意思?
    c# Socket tcpClient处理连接超时方式timeout
    不同网段服务器与客户端连接问题解决方法TCP/IP_C/S
    Http请求响应及SpringMVC相关注解解析
    Nginx部署项目,转发规则,负载均衡配置
    Linux redis设置后台启动
    Linux centos7安装Jdk nginx redis
    SpringCloud整合SpringSecurity JWT进行认证 ,鉴权
    C#中class与struct的区别概述
    列举ASP.NET 页面之间传递值的几种方式
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10650685.html
Copyright © 2011-2022 走看看