Luo Gu P1197 Star Wars - Star before the chain to use and simple

Forward star

Before understanding the chain to the star before you a quick view to the front under the stars. Forward star array is a set of edges, each edge first in ascending sort order, and if the same starting point, then in accordance with the ordered from small to large end, and record the starting position of each point in the array point and the number of edges attached.

  • \ (len [i] \) represented by \ (I \) the number of edges of the strip as a starting point, hehiad [i] represented by \ (I \) a first edge position as the origin stored in an array
  • head[1]=1,len[1]=3
  • head[2]=4,len[2]=1
  • head[3]=5,len[3]=1
  • head[4]=6,len[4]=2

Using a forward star, it may be \ (O (n \ log_2 { n}) \) within a time-ordered treatment +, \ (O (. 1) \) Query time

The former is particularly suitable for optimizing SPFA, DFS and BFS to star

Former chain to star

Use structure, adding the current address of the next side edge point of the head side of the array is stored in the address i as a starting point, next storage address of the next edge, = 0 indicates the last edge when the next.

#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;
}

Luo Gu P1197 Star Wars

The basic idea

Using reverse disjoint-set, to the status of the star before using chain store side, indicating whether the VIS is destroyed, by the last time the reverse reconstruction using disjoint-set number of inspection blocks Unicom

#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;
}

Guess you like

Origin www.cnblogs.com/tldr/p/11284891.html