首页 > 其他分享 >点对(强连通)

点对(强连通)

时间:2024-07-18 19:18:44浏览次数:9  
标签:连通 能到 int 哪个 顶点 胖点 size

https://www.luogu.com.cn/problem/P4306 第2题     点对 查看测评数据信息

给定一个N个节点的有向图,统计该有向图的点对个数,如下图:

image.png

顶点1可达1,2,3,4,5

顶点2可达2,3,4,5

顶点3可达3,4,5

顶点4,5都只能到达自身。

所以这张图的点对数为14.

给定一张图,请你求出它的点对数

对于100%的数据,1≤N≤2000

输入格式

 

输入数据第一行是图顶点的数量,一个正整数N.

接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。

 

输出格式

 

输出一个整数,表示点对数

 

输入/输出例子1

输入:

3

010

001

100

 

输出:

9

 

样例解释

 

 

想知道图中哪个点能到哪个点,1.建反图(拓扑),2.用bitset或运算,具体看本题

缩点,一个胖点内的点可以互相到达,所以另外一个胖点到这个胖点的点对数量就是相乘他们所包含的成员数即可

缩点后建个新图,我们可以统计每个胖点内点的个数,再统计从哪个点能到达哪个点,如果可以记录答案

假设u能到v,那么 ans+=size[u]*size[v],自身也要加到答案,因为有size[u]个点,胖点内每个点到每个点,也就是size[u]*size[u]

现在问题变成,怎么求u能到v,也就是统计哪个点能到哪个点

 

由于1能到的点是2,同时,2能到的点1也能到,所以1能到的点,就是他能到的点,所能到的点,一直推下去

定f[u][v]=1,表示u能到v

那么如果f[1][2]=1,那么f[1][3]=1,f[1][4]=1

 

策略:建反图,这样就能从图中最底下的点,反推到最上面的点,例如4能到3,3能到2,这时再跑到1,就可以知道1号点他能到的点,所能到的点是什么了

技巧:用bitset位运算的“|”,用二进制01代表能否到达某个点,例如此图的3号点,f[3]=0011,(注意,点到自身也是可以的)

我们只需要O(1)的时间,就能计算出 f[2] |= f[3] =0111

 

#include <bits/stdc++.h>
using namespace std;
const int N=2005;

int n, vis[N], ans=0, dfn[N], low[N], idx=0, cnt=0, id[N], size[N], d[N];
stack<int> st;
char c[N];
vector<int> a[N], b[N];
bitset<N> f[N];
queue<int> q;
void dfs(int u)
{
	dfn[u]=low[u]=++idx;
	st.push(u);
	
	for (int i=0; i<a[u].size(); i++)
	{
		int v=a[u][i];
		if (!dfn[v])
		{
			dfs(v);
			low[u]=min(low[u], low[v]);
		}
		else if (!id[v]) low[u]=min(low[u], dfn[v]);
	} 
	
	if (low[u]==dfn[u])
	{
		cnt++;
		while (st.top()!=u)
		{
			id[st.top()]=cnt;
			size[cnt]++;
			st.pop();
		}
		id[st.top()]=cnt;
		size[cnt]++;
		st.pop();
	}
}
void topsort()
{
	for (int i=1; i<=cnt; i++)
		if (!d[i]) q.push(i);
		
	while (!q.empty())
	{
		int u=q.front();
		q.pop();
		
		for (int i=0; i<b[u].size(); i++)
		{
			int v=b[u][i];
			f[v]|=f[u];
			d[v]--;
			if (!d[v]) q.push(v);
		}
	}
}
int main()
{
	scanf("%d", &n);
	for (int i=1; i<=n; i++)
	{
		scanf("%s", c+1);
		for (int j=1; j<=n; j++)
			if (c[j]=='1') a[i].push_back(j);
	}
	
	for (int i=1; i<=n; i++)
		if (!dfn[i]) dfs(i);
	
	for (int u=1; u<=n; u++)
		for (int j=0; j<a[u].size(); j++)
		{
			int v=a[u][j];
			if (id[u]!=id[v]) b[id[v]].push_back(id[u]), d[id[u]]++;
		}
	
	for (int i=1; i<=cnt; i++) f[i][i]=1;
	topsort();
	
	
	for (int i=1; i<=cnt; i++)
		for (int j=1; j<=cnt; j++)
			if (f[i][j]) ans+=size[i]*size[j];
	
	printf("%d", ans);
	
	return 0;
}
/*
5
01100
00101
00011
00000
00000
*/

  

标签:连通,能到,int,哪个,顶点,胖点,size
From: https://www.cnblogs.com/didiao233/p/18310283

相关文章

  • 遍历(强连通)
    https://www.luogu.com.cn/problem/P2194第3题   遍历 查看测评数据信息给定n个点,m条边的有向图,每个节点有一个权重v(i),你的任务是把n个点遍历一遍,点可以重复经过。允许的操作如下:每次你可以选择一个开始节点i,如果可以从i出发,最后可以回到i节点,那么你的花费为v(i)。问:最......
  • 朋友(强连通)
    https://www.luogu.com.cn/problem/P1407 第1题   朋友 查看测评数据信息我们已知n对男女朋友,称第i对朋友的男方为B(i),女方为G(i)。若某男B(i)与某女G(j)曾经是同学(无论是大学,高中,亦或是幼儿园阶段,i<=j),则当某方与其朋友(即B(i)与G(i)或B(j)与G(j))感情......
  • 连通性相关
    连通性相关强连通分量强连通分量(SCC):极大的强连通子图。Tarjan算法维护一个栈存储搜索到的还未确定强连通分量的点,定义:\(dfn_u\):节点\(u\)被搜索的次序。\(low_u\):\(u\)子树中能回溯到的最小的\(dfn\)。不难得到:一个点子树内的\(dfn\)大于该点的\(dfn\)。......
  • 图论连通性
    【学习笔记】图论连通性啊啊啊啊啊!先引用一篇犇的:)))缩点弱连通:对于有向图中两点\(x\)和\(y\),它们在所有边为无向时存在一个环使它们相连。强连通:对于有向图中两点\(x\)和\(y\),存在一个环使它们相连。强连通子图:对于有向图\(G=(V,E)\),如果对于一个\(V\)的子集......
  • 无向图的连通性(割点与割边)
    割点与割边 割点的求解方法  割点详解 板题:https://www.luogu.com.cn/problem/P3388  第1题   割点 查看测评数据信息给出一个n个点,m条边的无向图,求图的割点。输入格式 第一行输入两个正整数n,m。下面m行每行输入两个正整数x,y表示x到y有一......
  • 动态图连通性笔记
    首先离线的话有几种方法:线段树分治动态维护最大生成树:边的权值为他的(下一次)删除时间,加边正常做,询问时问路径最小值是否小于当前时刻.动态图连通性Holm-deLichtenberg-Thorup(HLT)暴力:维护生成森林,若删树边则暴力找另一条边能替代这条树边.思想:给每条边赋一个“不重......
  • 数据融合工具(6)线要素网络连通性分组计算
            出行,一直在使用导航辅助我们从起点奔赴终点,或许我们会有过这样的思考?导航路线规划是怎么实现的?        ……        我们先掰扯掰扯……一、导航路线规划是如何实现的?        导航路线规划是一种复杂的算法和技术,它用于确定......
  • 信息学奥赛初赛天天练-43-CSP-J2020基础题-链表、连通图、2进制转10进制、栈、队列、
    PDF文档公众号回复关键字:202407102020CSP-J选择题单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)7.链表不具有的特点是()A.可随机访问任一元素B.不必事先估计存储空间C.插入删除不需要移动元素D.所需空间与线性表长度成正比8.有10个顶点的无向图至少......
  • 强连通分量
    #include<bits/stdc++.h>usingnamespacestd;intn;//节点数量intG[1010][1010];//图的邻接矩阵表示intTime,sum;//Time用于记录DFS的时间,sum用于记录强连通分量的数量intbeg[1010],low[1010];//beg记录每个节点开始被访问的时间,low记录每个节点能够回溯到的最......
  • 卡码网刷题一之获取连通的相邻节点列表
     哇丢~~~果然工作后就没时间刷题了,先来个简单的试试水题目描述:在网元内,存在了N个转发节点,每个转发节点有自己唯一的标识TB且每个节点有M个端口,节点间通过端口进行报文通讯。出于业务隔离的需求,服务器内的端口被划分为多个通讯平面(用VLAN隔离,每个VLAN都有一个VLAN......