`

uva(Transitive Closure)

 
阅读更多

source: http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=388&problem=3063&mosmsg=Submission+received+with+ID+928527

title:Transitive Closure

题目简述:给出一个有向图,求有多少组(x, y)使得x到y有一条路径并且x不等于y。

解法: 强连通分量+拓扑排序+位运算#include <stdio.h>

#include <vector>
using namespace std;
/************************
init: stop,cnt,scnt, en置0; pre[]置-1, fir[]置NULL
CALL:for(i = 0; i < n; i++) if(-1 == pre[i]) tarjan(i, n);
************************/
#define V 2505
#define E 10005
typedef vector<int> vi;
const int K=V/30+5;
struct e{
	int v;
	e* nxt;
}es[E];
e* fir[V];
int id[V], pre[V], low[V], s[V], stop, cnt, scnt;
int en;
int n;
int num[V], size[V], tid[V];
vi son[V], rson[V];
int has[V][K];

void tarjan(int v, int n){
	int t, minc = low[v] = pre[v] = cnt++;
	e* cur;
	s[stop++] = v;
	for(cur = fir[v]; cur ; cur = cur->nxt){
		if(-1 == pre[cur->v]) tarjan(cur->v, n);
		if(low[cur->v] < minc) minc = low[cur->v];
	}
	if(minc < low[v]){
		low[v] = minc;
		return;
	}
	do{
		id[t = s[--stop]] = scnt; low[t] = n;
	}while(t != v);
	++scnt;   //强连通分量的个数
}
inline void add_e(int u, int v){
	es[en].v = v; es[en].nxt = fir[u]; fir[u] = &es[en++];
}
void getSCC(int n){  //get strongly connected component
	stop = cnt = scnt = 0;
	int i;
	for(i = 0; i < n; i++) pre[i] = -1;
	for(i = 0; i < n; i++) if(-1 == pre[i]) tarjan(i, n);
}

bool input(){
	scanf("%d", &n);
	int u, v, i, e;
	scanf("%d", &e);
	for(i = 0; i < n; i++) fir[i] = NULL;
	en = 0;
	while(e--){
		scanf("%d%d", &u, &v);
		u--; v--;
		add_e(u, v);
	}
	return true;
}
void topu(int id){
	pre[id]=0;
	int v, i, s;
	for(s=son[id].size(), i=0; i<s; i++){
		if(pre[v=son[id][i]]==-1){
			topu(v);
		}
	}
	tid[cnt++]=id;
}
void solve(){
	getSCC(n);
	int i, ans, u, v, k, j, s, h, g;
	e* cur;
	for(i=0; i<scnt; i++){
		son[i].clear();
		rson[i].clear();
		size[i]=0;
	}
	for(i=0; i<n; i++){
		size[u=id[i]]++;
		for(cur=fir[i]; cur; cur=cur->nxt){
			if((v=id[cur->v])!=u){
				son[u].push_back(v);
				rson[v].push_back(u);
			}
		}
	}
	for(ans=i=0; i<scnt; i++){
		ans += size[i]*(size[i]-1);
		pre[i]=-1;
	}
	cnt=0;
	k=scnt/30+(scnt%30==0 ? 0: 1);
	for(i=0; i<scnt; i++){
		if(pre[i]==-1){
			topu(i);
		}
		for(j=0; j<k; j++){
			has[i][j]=0;
		}
	}
	for(i=0; i<scnt; i++){
		u=tid[i];
		for(s=son[u].size(), j=0; j<s; j++){
			v=son[u][j];
			for(h=0; h<k; h++){
				has[u][h] |= has[v][h];
			}
			has[u][v/30] |= (1<<(v%30));
		}
		for(h=0; h<k; h++){
			v=has[u][h];
			for(g=0; v; v>>=1, g++){
				if(v&1){
					ans += size[u]*size[h*30+g];
				}
			}
		}
	}
	printf("%d\n", ans);
}
int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		input();
		solve();
	}
	return 0;
}
暴力广搜的版本:
#include <stdio.h>
#include <vector>
using namespace std;
/************************
init: stop,cnt,scnt, en置0; pre[]置-1, fir[]置NULL
CALL:for(i = 0; i < n; i++) if(-1 == pre[i]) tarjan(i, n);
************************/
#define V 2505
#define E 10005
typedef vector<int> vi;
const int K=V/30+5;
struct e{
	int v;
	e* nxt;
}es[E];
e* fir[V];
int id[V], pre[V], low[V], s[V], stop, cnt, scnt;
int en;
int n;
int num[V], size[V], tid[V], que[V];
vi son[V];
int has[V][K];

void tarjan(int v, int n){
	int t, minc = low[v] = pre[v] = cnt++;
	e* cur;
	s[stop++] = v;
	for(cur = fir[v]; cur ; cur = cur->nxt){
		if(-1 == pre[cur->v]) tarjan(cur->v, n);
		if(low[cur->v] < minc) minc = low[cur->v];
	}
	if(minc < low[v]){
		low[v] = minc;
		return;
	}
	do{
		id[t = s[--stop]] = scnt; low[t] = n;
	}while(t != v);
	++scnt;   //强连通分量的个数
}
inline void add_e(int u, int v){
	es[en].v = v; es[en].nxt = fir[u]; fir[u] = &es[en++];
}
void getSCC(int n){  //get strongly connected component
	stop = cnt = scnt = 0;
	int i;
	for(i = 0; i < n; i++) pre[i] = -1;
	for(i = 0; i < n; i++) if(-1 == pre[i]) tarjan(i, n);
}

bool input(){
	scanf("%d", &n);
	int u, v, i, e;
	scanf("%d", &e);
	for(i = 0; i < n; i++) fir[i] = NULL;
	en = 0;
	while(e--){
		scanf("%d%d", &u, &v);
		u--; v--;
		add_e(u, v);
	}
	return true;
}
int BFS(int s){
	int l, r, num, i, v, u, ans;
	pre[s]=s;
	for(ans=l=r=0, que[r++]=s; l!=r; ){
		 for(num=son[u=que[l++]].size(), i=0; i<num; i++){
			 if(pre[v=son[u][i]]!=s){
				 pre[v]=s;
				 ans+=size[s]*size[v];
				 que[r++]=v;
			 }
		 }
	}
	return ans;
}
void solve(){
	getSCC(n);
	int i, ans, u, v;
	e* cur;
	for(i=0; i<scnt; i++){
		son[i].clear();
		size[i]=0;
	}
	for(i=0; i<n; i++){
		size[u=id[i]]++;
		for(cur=fir[i]; cur; cur=cur->nxt){
			if((v=id[cur->v])!=u){
				son[u].push_back(v);
			}
		}
	}
	for(ans=i=0; i<scnt; i++){
		ans += size[i]*(size[i]-1);
		pre[i]=-1;
	}
	for(i=0; i<scnt; i++){
		ans+=BFS(i);
	}
	printf("%d\n", ans);
}
int main(){
	
	int t;
	scanf("%d", &t);
	while(t--){
		input();
		solve();
	}
	return 0;
}

分享到:
评论

相关推荐

    On Computing the Transitive Closure of a Relation PDF

    《计算二元关系的传递闭包》(On Computing the Transitive Closure of a Relation)涉及数学和编译器设计领域的核心概念。在数学中,传递闭包是通过添加最少的元素使一个二元关系具有传递性的过程。在编译器设计中...

    算法分类.txt

    传递闭包(Transitive Closure) 关节点(Articulation Point - UndiGraph) 拓扑排序(Topological Sort - AOV-Network) 关键路径(Critical Path - AOE-Network) 回路问题: 欧拉路(Euler Path), 汉密尔顿回路(Hamilton ...

    packing transitive triples in a tournament

    本文研究了锦标赛图(tournament)中关于传递三元组(transitive triple)和传递四元组(transitive quadruple)的最大弧不相交(arc-disjoint)打包数量问题。作者Mohamad Kabiya与Raphael Yuster在论文中证明了在...

    Aho Garey Ullman The transitive reduction of a directed

    Aho Garey Ullman The transitive reduction of a directed graphAho Garey Ullman The transitive reduction of a directed graphAho Garey Ullman The transitive reduction of a directed graphAho Garey ...

    Algorithms_and_Data_Structures_in_C++

    Index A Acyclic graph 66 Adder CLA adder module 200 ...Transitive closure 68, 80 Tree 67 2’s complement notation 7 U Unions 20, 33 Unsigned notation 5 V Visualization 52

    图论问题matlab工具箱

    grTranClos - built the transitive closure for the digraph; grTravSale - solve the nonsymmetrical traveling salesman problem; grValidation - auxiliary function (the data validation); grTheoryTest - ...

    Alternating groups and flag-transitive $2-(v,k,4)$ symmetric designs

    交错群与旗传递$2-(v,k,4)$对称设计,董会莉,周胜林,本文研究旗传递的2-(v,k,4)对称设计的分类。证明了如果旗传递点本原的2-(v,k,4) 对称设计D的自同构群G的基柱为交错群An,其中n&gt;=5, 则(v,k)=(15

    离散数学试题及答案合集

    - 关系的闭包: Reflexive closure, symmetric closure, transitive closure 等。 5. **代数结构**: - 群论:群的定义、运算性质、子群、同态。 - 环与域:加法和乘法结构的理解,整环、域的概念。 - 字母表和...

    迁移学习-杨强-2015_Transitive_Transfer_Learning1

    迁移学习-杨强-2015_Transitive_Transfer_Learning1 迁移学习是一种机器学习技术,通过利用源域的知识来增强目标域的学习能力。这种技术已经在各种应用中被证实是有效的。然而,迁移学习的一个主要限制是源域和目标...

    The Cayley graph built upon the semigroup of left ideals of a ring (2014年)

    We investigate the interaction between a ring R and the Cayley graph Cay(L(R)) of the semigroup of left ideals of R,as well as subdigraphs of this graph.Graph...such as transitive closure,girth,radius,di

    传递闭包的Matlab实现.rar

    在计算机科学中,传递闭包(Transitive Closure)是一个重要的概念,主要应用于图论和关系代数中。它表示在给定的关系集合中,通过一系列传递性步骤所能达到的所有连接。例如,在一个图中,如果节点A与节点B直接相连...

    transitive.js:运输数据可视化

    例如,一个旅程可以突出显示: 可以将Transitive地图作为独立的Web元素嵌入,也可以使用插件将其覆盖在地图上。 传递性得到 。 在阅读更多。故事书要查看实际中的Transitive样本, 。 您还可以在本地运行此命令: ...

    (原文+译文)2015_传递迁移学习_杨强团队_Transitive_Transfer_Learning.zip

    受人类传递性推理和学习能力的启发,利用辅助概念将两个看似无关的概念通过一系列中间桥连接起来,本文研究了一个新的学习问题:传递性转移学习(transitive Transfer learning,简称TTL)。TTL的目的是在源域和目标...

    IT软件硬件工程师常用英文词汇Java和python必备.docx

    * Transitive Closure and Reduction Computational Geometry: * Convex Hull * Triangulation * Voronoi Diagrams * Nearest Neighbor Search * Range Search Set and String Problems: * Set Cover * Set ...

    CPT107 离散数学 期末复习笔记配套例题

    - **4.2.3 Transitive Closure**: 求关系的传递闭包,找到所有可以通过有限次传递步骤到达的元素对。 - **4.3 Equivalence Relations**: 等价关系需满足自反性、对称性和传递性,证明一个关系是等价关系,需要分别...

    离散数学第44陈瑜PPT课件.pptx

    3. 传递闭包(Transitive Closure): 传递闭包t(R)确保了如果a与b有关系,b又与c有关系,那么a与c也具有关系。在这个例子中,, b&gt;和, c&gt;都在R中,所以t(R)会添加, c&gt;这一对,即使它没有在原始的R中出现。所以t(R)={,...

    标准化与模糊等价矩阵_模糊聚类_模糊化_

    这通常通过传递闭包(Transitive Closure)来实现,即如果A与B相似,B与C相似,那么A与C也相似。`TransitiveClosure.m` 文件很可能包含了实现模糊等价矩阵的传递闭包算法。 在实际应用中,模糊等价矩阵可以用来定义...

    计算机编程英语单词,这里总结了大部分编程所需了解的英文单词,对与程序开发人员有很好的帮助,可以帮助他们更流畅的阅读外文资料文档。

    3. 图论(Graph Theory):涉及到连通分支(Connected Components)、拓扑排序(Topological Sorting)、最小生成树(Minimum Spanning Tree)、最短路径(Shortest Path)、传递闭包(Transitive Closure and ...

    C++实现的传递壁报的求解及验证

    这段代码是用C++语言实现的一个程序,用于计算和验证传递闭包(Transitive Closure)的概念,这在图论和关系代数中是常见的概念。传递闭包是指在一个二元关系R上,如果存在元素a、b、c,使得a与b之间有关系R,且b与c...

Global site tag (gtag.js) - Google Analytics