为了能到远方,脚下的每一步都不能少.|

luckydrawbox

园龄:4个月粉丝:1关注:2

B3613 图的存储与出边的排序

Link\text{Link}

前置知识

图的存储排序

题意

给定一个 nn 个点 mm 条边的有向图 GG,结点编号从 11nn。对于 u=1,2,3,nu = 1, 2, 3, \dots n,依次完成如下要求: 对于 uu 的所有出边(即从 uu 出发的边),按照从小到大的顺序输出出边所指向的节点编号。

依次完成的含义是,先按顺序输出 u=1u = 1 的出边所指向的点的编号,再按顺序输出 u=2u = 2 的出边所指向的点的编号……最后按顺序输出 u=nu = n 的出边所指向的点的编号。

分析

这里给出两种做法:邻接表和链式前向星。

邻接表

  • 清空邻接表。
for(int i=1;i<=n;i++)
	e[i].clear();
  • 存边。
for(int i=1,x,y;i<=m;i++){
    x=read();y=read();
    e[x].push_back(y);
}
  • 对每个点的出边排序,并输出。
for(int i=1;i<=n;i++){
    sort(e[i].begin(),e[i].end());
    for(int j=0;j<e[i].size();j++)
        printf("%d ",e[i][j]);
    puts("");
}

链式前向星

  • 清空 headhead 数组,因为 m5×105\sum m\le 5\times10^5,所以 tot=0; 可加可不加。注意不能写成 memset(head,0,sizeof(head));,否则时间复杂度就变成 O(TN)(5×105)2=2.5×1011O(TN)\le(5\times10^5)^2=2.5\times10^{11} 级别的了。
for(int i=1;i<=n;i++)
	head[i]=0;
  • 存边
void add(int x,int y){
	ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;
}

for(int i=1,x,y;i<=m;i++){
    x=read();y=read();
    add(x,y);
}
  • 把每个点的出边放入 vector\text{vector} 类型的 ee 或一个数组 中,注意前面要清空,然后排序并输出(那还不如直接用邻接表
for(int i=1;i<=n;i++){
    e.clear();
    for(int j=head[i];j;j=nxt[j])
        e.push_back(ver[j]);
    sort(e.begin(),e.end());
    for(int j=0;j<e.size();j++)
        printf("%d ",e[j]);
    puts("");
}

以上两种做法的复杂度都是 O(nlogn)O(n\log n)

代码

邻接表

#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
const int N=5e5+10;
int t,n,m;
vector<int>e[N];
int main(){
	t=read();
	while(t--){
		n=read();m=read();
		for(int i=1;i<=n;i++)
			e[i].clear();
		for(int i=1,x,y;i<=m;i++){
			x=read();y=read();
			e[x].push_back(y);
		}
		for(int i=1;i<=n;i++){
			sort(e[i].begin(),e[i].end());
			for(int j=0;j<e[i].size();j++)
				printf("%d ",e[i][j]);
			puts("");
		}
	}
	return 0;
}

链式前向星

#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
const int N=5e5+10;
int t,n,m;
int head[N],nxt[N<<1],ver[N<<1],tot;
void add(int x,int y){
	ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;
}
vector<int>e;
int main(){
	t=read();
	while(t--){
		n=read();m=read();
		for(int i=1;i<=n;i++)
			head[i]=0;
		for(int i=1,x,y;i<=m;i++){
			x=read();y=read();
			add(x,y);
		}
		for(int i=1;i<=n;i++){
			e.clear();
			for(int j=head[i];j;j=nxt[j])
				e.push_back(ver[j]);
			sort(e.begin(),e.end());
			for(int j=0;j<e.size();j++)
				printf("%d ",e[j]);
			puts("");
		}
	}
	return 0;
}

本文作者:luckydrawbox

本文链接:https://www.cnblogs.com/luckydrawbox/p/18526564

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   luckydrawbox  阅读(23)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起