zoukankan      html  css  js  c++  java
  • dtoj#4299. 图(graph)

    题目描述:

    对于一个无向图 $G$,三元组 $(a, b, c)$ 被称为优秀的当且仅当满足如下条件:

    $1. a < b < c$;

    $2. a $ 与 $b$ 有边相连;

    $3. a $ 与 $c$ 有边相连;

    $4. b$ 与 $c$ 没有边相连。

    现在有一个 $n$ 个点的连通无向图 $G$,每次找一个优秀的三元组 $(a, b, c)$ 将 $b$ 和 $c$ 连边,如果没有则结束加边过程。

    问最终得到的图有多少种用 $n$ 种颜色对点染色的方案,对 $998244353$ 取模后输出。

    一种染色方案合法当且仅当每个点颜色是 $1$ 到 $n$ 中的一个,并且一条边两端的点颜色不同。

    算法标签:线段树合并

    思路:

    对于一个无向图 $G$,三元组 $(a, b, c)$ 被称为优秀的当且仅当满足如下条件:

    $1. a < b < c$;

    $2. a $ 与 $b$ 有边相连;

    $3. a $ 与 $c$ 有边相连;

    $4. b$ 与 $c$ 没有边相连。

    现在有一个 $n$ 个点的连通无向图 $G$,每次找一个优秀的三元组 $(a, b, c)$ 将 $b$ 和 $c$ 连边,如果没有则结束加边过程。

    问最终得到的图有多少种用 $n$ 种颜色对点染色的方案,对 $998244353$ 取模后输出。

    一种染色方案合法当且仅当每个点颜色是 $1$ 到 $n$ 中的一个,并且一条边两端的点颜色不同。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e6+5,p=998244353;
    int n,m,rt[N],fa[N],cnt,tot,head[N],ne[N<<1],to[N<<1],ans=1;
    struct node{
        int x,l,r,num;
    }t[N*21];
    il int read(){
       int x,f=1;char ch;
       _(!)ch=='-'?f=-1:f;x=ch^48;
       _()x=(x<<1)+(x<<3)+(ch^48);
       return f*x;
    }
    il void ins(int x,int y){
        ne[++tot]=head[x];
        head[x]=tot;to[tot]=y;
    }
    il int getfa(int x){
        return fa[x]?(fa[x]=getfa(fa[x])):x;
    }
    il void update(int x){
        t[x].num=t[t[x].l].num+t[t[x].r].num;
    }
    il void insert(int &x,int l,int r,int pos){
        if(!x)x=++cnt;
        if(l==r){t[x].num=1;return;}
        int mid=(l+r)>>1;
        if(pos<=mid)insert(t[x].l,l,mid,pos);
        else insert(t[x].r,mid+1,r,pos);
        update(x);
    }
    il void merge(int &x,int y,int l,int r){
        if(!x||!y){x=x+y;return;}
        if(l==r){t[x].num=1;return;}
        int mid=(l+r)>>1;
        merge(t[x].l,t[y].l,l,mid);
        merge(t[x].r,t[y].r,mid+1,r);
        update(x);
    }
    il int query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return t[x].num;
        int mid=(l+r)>>1;int res=0;
        if(ql<=mid)res=query(t[x].l,l,mid,ql,qr);
        if(mid<qr)res+=query(t[x].r,mid+1,r,ql,qr);
        return res;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            ins(x,y);ins(y,x);
            insert(rt[min(x,y)],1,n,max(x,y));
        }
        for(int i=1;i<=n;i++){
            int f1=getfa(i);
            for(int j=head[i];j;j=ne[j]){
                int f2=getfa(to[j]);
                if(to[j]<i&&(f2^f1))merge(rt[f1],rt[f2],1,n),fa[f2]=f1;
            }
            ans=1ll*ans*(n-query(rt[f1],1,n,i+1,n))%p;
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    java对象和json对象之间互相转换
    SVN使用教程总结
    JVM调优总结-调优方法
    tomcat 高并发配置 与优化
    redis的主从复制配置
    Java实现Redis持久化到数据库的关键方法
    java操作redis
    SSO系统的实现
    jedisClient操作redis实现增删改查功能
    get与post
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10610421.html
Copyright © 2011-2022 走看看