zoukankan      html  css  js  c++  java
  • 洛谷P1197星球大战-链式前向星及其简单运用

    前向星

    在了解链式前向星之前,先简单了解下前向星。前向星是一种边集数组,先把每条边按照从小到大的顺序排序,如果起点一样,那么就按照终点从小到大来排序,并记录下每个点为起点在数组中的位置和该点所连边的数量。

    • (len[i])表示以(i)为起点的边的条数,hehiad[i]表示以(i)为起点的边在数组中存储的第一个位置
    • head[1]=1,len[1]=3
    • head[2]=4,len[2]=1
    • head[3]=5,len[3]=1
    • head[4]=6,len[4]=2

    利用前向星,可以在(O(nlog_2{n}))时间内排序+处理,(O(1))时间内查询

    前向星特别适合优化SPFA,DFS和BFS

    链式前向星

    使用结构体,添加了当前边指向的下一条边的地址,head数组存放以i为起点的边的地址,next存放下一条边的地址,当next=0时表示最后一条边。

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100501
    struct NODE{
    	int w;
    	int e;
    	int next; //next[i]表示与第i条边同起点的上一条边的储存位置
    }edge[MAXN];
    int cnt;
    int head[MAXN]; 
    void add(int u,int v,int w){
    	edge[cnt].w=w;
    	edge[cnt].e=v;    //edge[i]表示第i条边的终点 
    	edge[cnt].next=head[u]; //head[i]表示以i为起点的最后一条边的储存位置 
    	head[u]=cnt++;
    }
    int main(){
    	memset(head,0,sizeof(head));
    	cnt=1;
    	int n;
    	cin>>n;
    	int a,b,c;
    	while(n--){
    		cin>>a>>b>>c;
    		add(a,b,c);
    	}
    	int start;
    	cin>>start;
    	for(int i=head[start];i!=0;i=edge[i].next)
    	   cout<<start<<"->"<<edge[i].e<<" "<<edge[i].w<<endl;
    	return 0;
    }
    

    洛谷P1197 星球大战

    基本思路

    使用反并查集,使用链式前向星存储边的状况,vis表示是否被摧毁,由最后时刻反向重建,使用并查集检查联通块数目

    #include<bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);
    #define ll long long
    #define INF  0x7f7f7f7f;
    #define MAXN 500010
    #define ok1 cout<<"OK1"<<endl
    #define ok2 cout<<"OK2"<<endl
    #define ok3 cout<<"OK3"<<endl
    #define MOD 10007
    using namespace std;
    int f[MAXN],store[MAXN],ans[MAXN];
    int cnt=0;bool vis[MAXN];	int h[MAXN];
    typedef struct{
    	int w,from,to,next;
    }EDGE; EDGE edges[MAXN];
    void add(int u,int v)
    {//链式前向星 
    	edges[cnt].from=u;
    	edges[cnt].to=v;
    	edges[cnt].next=h[u];
    	h[u]=cnt++;
    }
    int find(int x)
    {//路径压缩 
    	if(f[x]!=x) f[x]=find(f[x]);
    	return f[x];
    }
    int main()
    {
    	int n,m,a,b,k,x;
    	cin>>n>>m;
    
    	fill(h,h+MAXN,-1);
    	memset(vis,false,sizeof(vis));
    	FOR(i,0,n)
    	{
    		f[i]=i;
    	} 
    	FOR(i,0,m)
    	{
    		cin>>a>>b;
    		add(a,b);add(b,a);//无向图 
    	}
    	cin>>k;
    	int total=n-k;
    	FOR(i,0,k)
    	{
    		cin>>x;
    		store[i]=x;
    		vis[x]=true;//全部毁灭 
    	}
    	FOR(i,0,2*m)
    	{
    		if(vis[edges[i].from]==false&&vis[edges[i].to]==false)
    		{//不是被毁灭的点 
    			int fa=find(edges[i].from);
    			int fb=find(edges[i].to);
    			if(fa!=fb)
    			{
    				f[fa]=fb;
    				total--;//计算联通块,若能本来不联通,联通块数目-- ,本来联通则不变 
    			}
    		}
    	}
    	ans[k]=total; //倒着重建
    	for(int i=k-1;i>=0;i--) 
    	{
    		int u=store[i];
    		total++;
    		vis[u]=false;
    		for(int j=h[u];j!=-1;j=edges[j].next)
    		{
    			if(vis[edges[j].to]==false){
    				int fa=find(edges[j].from);
    				int fb=find(edges[j].to);
    				if(fa!=fb){
    					f[fa]=fb;
    					total--;//本来不连通,重建后联通 ,本来联通就不变 
    				} 
    			} 
    		}
    		ans[i]=total;
    	} 
    	FOR2(i,0,k) 
    		cout<<ans[i]<<endl; 
    	return 0;
    }
    
  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/tldr/p/11284891.html
Copyright © 2011-2022 走看看