• 邻接表存图的小trick(存多个图)


    我常用如下的邻接表存图的方式:

    int head[N], next[M*2], ver[M*2], edge_tot;
    void add_edge(int x,int y) {
        ver[++edge_tot] = y;
        next[edge_tot] = head[x];
        head[x] = edge_tot;
    }
    

    对于要存多图张图的场景来说, 一个直观的想法是将上面所用数组和函数大体复制一遍, 然后对命名独立区分,即:

    int head2[N], next2[M*2], ver2[M*2], edge_tot2;
    void add_edge2(int x,int y) {
        ver2[++edge_tot2] = y;
        next2[edge_tot2] = head2[x];
        head2[x] = edge_tot2;
    }
    

    但是说白了, 邻接表不过是从所有边组成的集合里拿出一部分变成一条链挂在了标号上……

    用邻接表的方法存多张图本质上就是对每个点存多个邻接边集, 每个邻接边集属于某张图。

    所以存多个图只需要多开 head 就行了(对于一张图, 一条链就是一个点的邻接边集)。

    常用的遍历一条边的算法就变成这样:

    for(int i=head[K][x];i;i=next[i]) {
        int y=ver[i], z=weight[i];
        \ balabala
    }
    

    只需要在 i=head[x] 处做一些微小的改变, 以区分在不同图中某个标号的点的相邻边, 这种区分也是必要的。

    个人是推荐这种方法存多图的, 因为大多数人还是挺熟悉邻接表的, 学这种方法成本极低。

    不过要得到一张图的边的数量嘛……再开数组记录吧?

    示例:

    Luogu的DAG缩点+DP模板题

    我扒出来以前的代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e4+15;
    const int M = 1e5+15;
    
    int n, m, val[N], val2[N];
    
    int ct, hd[N], nt[M<<1], vr[M<<1];
    void ad(int a,int b) {
    	vr[++ct]=b, nt[ct]=hd[a], hd[a]=ct;
    }
    
    int deg[N];
    int ct2, hd2[N], nt2[M<<1], vr2[M<<1];
    void ad2(int a,int b) {
    	vr2[++ct2]=b, nt2[ct2]=hd2[a], hd2[a]=ct2;
    }
    
    int sccno[N], scccnt;
    int S[N], tp;
    int dfn[N], low[N], clk;
    void dfs(int x) {
    	dfn[x]=low[x]= ++clk;
    	S[++tp]=x;
    	for(int i=hd[x];i;i=nt[i]) {
    		int y=vr[i];
    		if(!dfn[y]) {
    			dfs(y);
    			low[x]=min(low[x],low[y]);
    		} else if(!sccno[y]) low[x]=min(low[x],dfn[y]);
    	}
    	if(low[x]==dfn[x]) {
    		++scccnt;
    		while(1) {
    			int u=S[tp--];
    			sccno[u] = scccnt;
    			if(u==x) break;
    		}
    	}
    }
    
    int f[N];
    int q[N], h=1, t=0;
    void topo() {
    	for(int i=1;i<=scccnt;++i) if(!deg[i]) f[q[++t]=i] = val2[i];
    	while(h<=t) {
    		int x=q[h++];
    		for(int i=hd2[x];i;i=nt2[i]) {
    			int y=vr2[i];
    			f[y] = max(f[y], f[x]+val2[y]);
    			if(--deg[y] == 0) q[++t] = y;
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for(int i=1;i<=n;++i) scanf("%d", &val[i]);
    	for(int i=0,x,y;i<m;++i) {
    		scanf("%d%d",&x,&y); ad(x,y);
    	}
    	for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i);
    	for(int x=1;x<=n;++x) {
    		val2[sccno[x]] += val[x];
    		for(int j=hd[x];j;j=nt[j]) {
    			int y=vr[j];
    			if(sccno[x] != sccno[y]) ad2(sccno[x],sccno[y]), ++deg[sccno[y]];
    		}
    	}
    	
    	topo();
    	int ans = 0;
    	for(int i=1;i<=scccnt;++i) ans=max(ans, f[i]);
    	cout << ans;
    	return 0;
    }
    

    修改一下, AC记录

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e4+15;
    const int M = 1e5+15;
    
    int n, m, val[N], val2[N];
    
    int ct, hd[3][N], nt[M<<2], vr[M<<2];
    void ad(int id,int a,int b) {
    	vr[++ct]=b, nt[ct]=hd[id][a], hd[id][a]=ct;
    }
    
    int deg[N];
    
    int sccno[N], scccnt;
    int S[N], tp;
    int dfn[N], low[N], clk;
    void dfs(int x) {
    	dfn[x]=low[x]= ++clk;
    	S[++tp]=x;
    	for(int i=hd[1][x];i;i=nt[i]) {
    		int y=vr[i];
    		if(!dfn[y]) {
    			dfs(y);
    			low[x]=min(low[x],low[y]);
    		} else if(!sccno[y]) low[x]=min(low[x],dfn[y]);
    	}
    	if(low[x]==dfn[x]) {
    		++scccnt;
    		while(1) {
    			int u=S[tp--];
    			sccno[u] = scccnt;
    			if(u==x) break;
    		}
    	}
    }
    
    int f[N];
    int q[N], h=1, t=0;
    void topo() {
    	for(int i=1;i<=scccnt;++i) if(!deg[i]) f[q[++t]=i] = val2[i];
    	while(h<=t) {
    		int x=q[h++];
    		for(int i=hd[2][x];i;i=nt[i]) {
    			int y=vr[i];
    			f[y] = max(f[y], f[x]+val2[y]);
    			if(--deg[y] == 0) q[++t] = y;
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for(int i=1;i<=n;++i) scanf("%d", &val[i]);
    	for(int i=0,x,y;i<m;++i) {
    		scanf("%d%d",&x,&y); ad(1,x,y);
    	}
    	for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i);
    	for(int x=1;x<=n;++x) {
    		val2[sccno[x]] += val[x];
    		for(int j=hd[1][x];j;j=nt[j]) {
    			int y=vr[j];
    			if(sccno[x] != sccno[y]) ad(2,sccno[x],sccno[y]), ++deg[sccno[y]];
    		}
    	}
    	
    	topo();
    	int ans = 0;
    	for(int i=1;i<=scccnt;++i) ans=max(ans, f[i]);
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    The Problem Came Up when we upgrade from KingDee K3 to SAP R3(FI module)
    小代码 OpenFileDialog() Windows下Upload & rewrite 文件
    [Note]CodeSmith 4.0 Lesson One
    正则表达式 运算 常见
    SAP function overview & instruction
    CodeSmith NetTier 保存主从表实例,当然,至于3级关联的问题还是类似做法,依靠Relationship做级联更新
    CodeSmith NetTier模板生成的代码框架用法 (转)
    [Notes] Demo The practice about how to using SAP XI components to build up the mapping bridge cross the application layer
    6260/7610/6670/3230 蓝牙 共享PC 宽带 无须代理
    [ALE in SAP]BAPI Introduction
  • 原文地址:https://www.cnblogs.com/tztqwq/p/13651986.html
Copyright © 2020-2023  润新知