zoukankan      html  css  js  c++  java
  • newcoder 14394 手铐 |Tarjan

    链接:https://ac.nowcoder.com/acm/problem/14394
    来源:牛客网

    题目描述

    给你一个连通无向图,保证每个点最多属于一个简单环,每个点度数最多为3,求这个图有多少“手铐图形个数”

    其中“手铐图形个数”,定义为三元组(x,y,S),其中x和y表示图上的两个点,S表示一条x到y的简单路径,而且必须满足:

    1.x和y分别在两个不同的简单环上

    2.x所在的简单环与路径S的所有交点仅有x,y所在的简单环与路径S的所有交点仅有y。

    (x,y,S)与(y,x,S)算同一个手铐

    如果你无法理解,可以参考样例。

    输入描述:

    第一行两个数n和m
    之后m行,每行两个数x,y表示x和y之间有一条边。

    输出描述:

    输出一个数,表示手铐的个数对19260817取模的结果


    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<map>
    #include<iomanip>
    #include<vector>
    using namespace std;
    const int N=1e6+5,M=4e6+5,mod=19260817;
    int nxt[M],head[N],go[M],tot=1;
    inline void add(int u,int v){
    	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
    	nxt[++tot]=head[v],head[v]=tot,go[tot]=u;
    }
    int n,m;
    inline int read(){
        int x=0; char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
        return x;
    }
    int dfn[N],low[N],co[N],st[N],si[N],col,num,top;
    inline void Tarjan(int u,int fr){
    	dfn[u]=low[u]=++num;
    	st[++top]=u;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		if(v==fr)continue;
    		if(!dfn[v]){
    			Tarjan(v,u);
    			low[u]=min(low[u],low[v]);
    		}else if(!co[v])low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]){
    		co[u]=++col;
    		si[col]=1;
    		while(st[top]!=u){
    			co[st[top]]=col;
    			si[col]++;
    			--top;
    		}
    		--top;
    	}
    }
    struct node{
    	int u,v;
    }e[M];
    long long ans[N],f[N];
    void DFS_dp(int x,int fa){
        ans[x]=0;
        if(si[x]>1)f[x]=1;
        else f[x]=0;
        for(int i=head[x];i;i=nxt[i]){
            int y=go[i];
            if(y==fa)continue;
            DFS_dp(y,x);
            ans[x]=(ans[x]+f[x]*f[y]%mod+ans[y])%mod;
            if(si[x]>1)f[x]=(f[x]+f[y]*2)%mod;
            else f[x]=(f[x]+f[y])%mod;
        }
    }
    int main(){
    	n=read(),m=read();
    	for(int i=1,u,v;i<=m;i++){
    		u=read(),v=read();
    		e[i]=(node){u,v};
    		add(u,v);
    	}
    	for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,0);
    	memset(nxt,0,sizeof(nxt)),tot=1;
    	memset(head,0,sizeof(head));
    	
    	for(int i=1;i<=m;i++){
    		if(co[e[i].u]==co[e[i].v])continue;
    		add(co[e[i].u],co[e[i].v]);
    	}
    	DFS_dp(1,0);
    	printf("%lld
    ",ans[1]);
    }
    
  • 相关阅读:
    Latex: 插入数学公式
    Matlab: 作图
    Random Access Iterator 2019 ICPC 徐州网络赛(树上概率DP)
    2019南京网络赛D Robots(概率DP+拓扑序)
    HDU3507 Print Article(斜率优化+单调队列)
    hdu4632(区间dp)
    POJ 1651 Multiplication Puzzle 区间DP
    暑假集训
    POJ-2955(区间DP)
    kuangbin计算几何模板转载
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12762878.html
Copyright © 2011-2022 走看看