• 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
  • 相关阅读:
    BOI 2002 双调路径
    BOI'98 DAY 2 TASK 1 CONFERENCE CALL Dijkstra/Dijkstra+priority_queue/SPFA
    USACO 2013 November Contest, Silver Problem 2. Crowded Cows 单调队列
    BOI 2003 Problem. Spaceship
    USACO 2006 November Contest Problem. Road Blocks SPFA
    CEOI 2004 Trial session Problem. Journey DFS
    USACO 2015 January Contest, Silver Problem 2. Cow Routing Dijkstra
    LG P1233 木棍加工 动态规划,Dilworth
    LG P1020 导弹拦截 Dilworth
    USACO 2007 February Contest, Silver Problem 3. Silver Cow Party SPFA
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10610421.html
Copyright © 2020-2023  润新知