• [CC-LONCYC]Lonely Cycles


    [CC-LONCYC]Lonely Cycles

    题目大意:

    (T(Tle1000))组数据。

    给定一张简单图(不含重边与自环),图中有(n(nle2 imes10^5))个节点和(m(sum n+mle5 imes10^6))条边。每个节点最多属于一个简单环。

    对于每条边,求出有多少简单路径包含这条边且至多包含一条在简单环上的边。

    思路:

    缩点后根据是否为环上边讨论,环上边的方案数就是两边结点数之积。去掉这些环就只剩下若干棵树,可以树形DP。

    源代码:

    #include<stack>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    typedef long long int64;
    const int N=2e5+1,M=5e6;
    struct Edge2 {
    	int u,v,id;
    };
    Edge2 edge[M];
    struct Edge {
    	int to,id;
    };
    std::vector<Edge> e[N];
    inline void add_edge(const int &u,const int &v,const int &id) {
    	e[u].push_back((Edge){v,id});
    	e[v].push_back((Edge){u,id});
    }
    bool ins[N],vis[N];
    std::stack<int> s;
    int dfn[N],low[N],scc[N],size[N],top[N],par[N],sum[N];
    int64 ans[M];
    void tarjan(const int &x,const int &par) {
    	s.push(x);
    	ins[x]=true;
    	dfn[x]=low[x]=++dfn[0];
    	for(auto &j:e[x]) {
    		const int &y=j.to;
    		if(y==par) continue;
    		if(!dfn[y]) {
    			tarjan(y,x);
    			low[x]=std::min(low[x],low[y]);
    		} else if(ins[y]) {
    			low[x]=std::min(low[x],dfn[y]);
    		}
    	}
    	if(dfn[x]==low[x]) {
    		scc[0]++;
    		int y;
    		do {
    			y=s.top();
    			s.pop();
    			ins[y]=false;
    			scc[y]=scc[0];
    		} while(y!=x);
    	}
    }
    void dfs(const int &x,const int &par) {
    	::par[x]=par;
    	size[x]=vis[x]=1;
    	top[x]=par?top[par]:x;
    	for(auto &j:e[x]) {
    		const int &y=j.to;
    		if(y==par||scc[x]==scc[y]) continue;
    		dfs(y,x);
    		size[x]+=size[y];
    	}
    }
    void dp1(const int &x) {
    	for(auto &j:e[x]) {
    		const int &y=j.to;
    		if(y==par[x]||top[x]!=top[y]) continue;
    		dp1(y);
    		sum[x]+=sum[y];
    	}
    }
    void dp2(const int &x) {
    	for(auto &j:e[x]) {
    		const int &y=j.to,&id=j.id;
    		if(y==par[x]||top[x]!=top[y]) continue;
    		dp2(y);
    		ans[id]+=(int64)(size[top[x]]-size[y])*size[y];
    		ans[id]+=(int64)(sum[top[x]]-sum[y])*size[y];
    		ans[id]+=(int64)sum[y]*(size[top[x]]-size[y]);
    	}
    }
    int main() {
    	for(register int T=getint();T;T--) {
    		const int n=getint(),m=getint();
    		for(register int i=0;i<m;i++) {
    			edge[i].u=getint();
    			edge[i].v=getint();
    			edge[i].id=i;
    			add_edge(edge[i].u,edge[i].v,i);
    		}
    		for(register int i=1;i<=n;i++) {
    			if(!dfn[i]) tarjan(i,0);
    		}
    		for(register int i=1;i<=n;i++) {
    			if(!vis[i]) dfs(i,0);
    		}
    		for(register int i=0;i<m;i++) {
    			const int &u=edge[i].u,&v=edge[i].v;
    			if(scc[u]!=scc[v]) continue;
    			ans[i]=(int64)size[top[u]]*size[top[v]];
    			sum[u]+=size[top[v]];
    			sum[v]+=size[top[u]];
    		}
    		for(register int i=1;i<=n;i++) {
    			if(i==top[i]) dp1(i);
    		}
    		for(register int i=1;i<=n;i++) {
    			if(i==top[i]) dp2(i);
    		}
    		for(register int i=0;i<m;i++) {
    			printf("%lld
    ",ans[i]);
    		}
    		//Reset
    		for(register int i=1;i<=n;i++) {
    			e[i].clear();
    		}
    		std::fill(&sum[1],&sum[n]+1,0);
    		std::fill(&dfn[0],&dfn[n]+1,0);
    		std::fill(&ans[0],&ans[m],0);
    		std::fill(&vis[1],&vis[n]+1,false);
    		scc[0]=0;
    	}
    	return 0;
    }
    
  • 相关阅读:
    React native 之 图标库ECharts的使用
    使用jquery给html标签加点击事件
    React native 之 async/await
    CSS布局之flexbox
    Swiper 的引入
    给浏览器设置一张背景图,并且拉动浏览器大小时图片不要被压缩变形
    境界的彼方_lduoj_bfs宽搜
    2021美国大学生数学建模大赛==ABCDEF+思路解析==
    3045 Lcm与Gcd构造
    对拍程序
  • 原文地址:https://www.cnblogs.com/skylee03/p/9740938.html
Copyright © 2020-2023  润新知