【UNR #2】UOJ拯救计划

UOJ小清新题表

题目内容

UOJ链接

题面太长了(其实是我懒得改LaTeX了)
一句话题意:
给出 \(n\) 个点和 \(m\) 条边,对其进行染色,共 \(k\) 种颜色,要求同一条边两点颜色不同,输出方案数\(\pmod 6\)

数据范围

\(1\leq n\leq 10^5,0\leq m\leq 2\times 10^5,1\leq k\leq 10^4\)

思路

水题解,他不香吗

由于本人并不会UOJ中的其他题,所以来水最简单的一道了

直接计算的话,答案为:

\[\sum\limits^k_{i=1}A^i_k\times x \]

其中\(x\)为用\(i\)种颜色的方案数,不过你可能惊喜的发现这个是个\(NPC\)问题。

所以为什么我要在一句话题意中把\(\text{mod}\ 6\)写上呢,因为当\(i\geq 3\)的时候,答案肯定为0。

所以好像只需要讨论\(i=1,2\)即可。

  • \(i=1\)
    • \(m=0\),直接是一堆点,\(ans=1\)
    • \(m\not=0\),那么只能\(ans=0\)
  • \(i=2\)
    • \(m=0\),对于\(n\)个点都有\(2\)种颜色可选,\(ans=k^2\)
    • \(m\not=0\),设图中共有\(tot\)个联通块,\(ans=C^2_k\times 2^{tot}\)。当然如果发现有一个联通块无法完成染色,答案就直接是\(0\)

然后其实\(m=0\)的时候直接答案就是\(k^n\)就行。

代码

#include <bits/stdc++.h>
#define int long long
#define Clean(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn=5e5+10;
const int Mod=6;
int n,m,k;
int vis[maxn];

struct Edge{
    int from,to,w,nxt;
}e[maxn<<1];

inline int read(){
    int x=0,fopt=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')fopt=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        x=(x<<3)+(x<<1)+ch-48;
        ch=getchar();
    }
    return x*fopt;
}

int head[maxn],cnt;
inline void add(int u,int v){
    e[++cnt].from=u;
    e[cnt].to=v;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}

inline int qpow(int x,int b){
    int ans=1,base=x;
    while(b){
        if(b&1)ans=ans*base%Mod;
        base=base*base%Mod;
        b>>=1;
    }
    return ans;
}

bool dfs(int u,int col){
    vis[u]=col;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(!vis[v]){
            if(!dfs(v,-col))return 0;
        }else if(vis[u]==vis[v])return 0;
        
    }
    return 1;
}

inline void Init(){
    cnt=0;
    Clean(e);
    Clean(head);
    Clean(vis);
}

signed main(){
    int T=read();
    while(T--){
        n=read();m=read();k=read();
        if(m==0){
            printf("%lld\n",qpow(k,n));
            continue;
        }else{
            if(k==1){
                for(int i=1;i<=m;i++){
                    read();read();
                }
                puts("0");
                continue;
            }else{
                Init();
                for(int i=1;i<=m;i++){
                    int u=read(),v=read();
                    add(u,v);add(v,u);
                }
                int tot=0,flag=1;
                for(int i=1;i<=n;i++){
                    if(!vis[i]){
                        if(dfs(i,1))tot++;
                        else{
                            flag=0;break;
                        }
                    }
                }
                printf("%lld\n",(k*(k-1)/2)%Mod*qpow(2,tot)*flag%Mod);
            }
        }
    }
    return 0;
}
posted @ 2020-08-15 07:20  Midoria7  阅读(115)  评论(0编辑  收藏  举报