codeforces 757F 求最短路后建立DAG后跑灭绝树

https://codeforces.com/contest/757/problem/F

题解如标题所述,

tarjan支配树2500ms,TLE10

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define ll long long
#define ull unsigned long long
#define fi first
#define endl '\n'
#define se second
#define mp make_pair
#define pii pair<ll,ll>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
const int maxn=1e6+9,maxm=1e9+10,maxp=20;
const ll INF=1e18;
using namespace std;
int casn,n,m,k,root;
int cntin[maxn];
struct node{int to,next;};
struct graph{
  node e[maxn];int head[maxn],nume;
  void init(int n=maxn-5){nume=0;fill_n(head,n+1,0);}
  void add(int a,int b){e[++nume]={b,head[a]};head[a]=nume;}
}inv,nxt,dom;
class domtree{public://@dom为最终的支配树,反向建边,root为根,cnt为每个点的支配点的数量@
  int dfn[maxn],rev[maxn],anc[maxn];
  int semi[maxn],idom[maxn];
  int fa[maxn],mi[maxn],clo;
  void  init(int n=maxn-5){
    clo=0;
    rep(i,1,n)fa[i]=mi[i]=semi[i]=i,rev[i]=dfn[i]=anc[i]=idom[i]=0;
    nxt.init(n),inv.init(n),dom.init(n);
  }
  void add(int a,int b){inv.add(b,a),nxt.add(a,b);}
  int find(int now){
    if(fa[now]==now) return now;
    int fx=fa[now],y=find(fa[now]);
    if(dfn[semi[mi[fx]]]<dfn[semi[mi[now]]])
      mi[now]=mi[fx];
    return fa[now]=y;
  }
  void tdfs(int now){
    dfn[now]=++clo;rev[clo]=now;
    forn(i,now,nxt.head,nxt.e)if(!dfn[nxt.e[i].to])
      anc[nxt.e[i].to]=now,tdfs(nxt.e[i].to);
  }
  void maketree(int root,int n=maxn-5){
    tdfs(root);
    per(i,2,n){
      int now=rev[i],tmp=n;
      forn(i,now,inv.head,inv.e){
        int to=inv.e[i].to;if(!dfn[to]) continue;
        if(dfn[to]<dfn[now]) tmp=min(tmp,dfn[to]);
        else find(to),tmp=min(tmp,dfn[semi[mi[to]]]);
      }
      semi[now]=rev[tmp];fa[now]=anc[now];
      dom.add(semi[now],now);
      now=rev[i-1];
      forn(i,now,dom.head,dom.e){
        int to=dom.e[i].to;find(to);
        if(semi[mi[to]]==now) idom[to]=now;
        else idom[to]=mi[to];
      }
    }
    rep(i,2,n){
      int to=rev[i];
      if(idom[to]!=semi[to]) idom[to]=idom[idom[to]];
    }
    dom.init(n);
    rep(i,1,n) if(i!=root)dom.add(idom[i],i);
  }
  int ans[maxn];
  int cal(int now){
    ans[now]=1;
    forn(i,now,dom.head,dom.e) ans[now]+=cal(dom.e[i].to);
    return ans[now];
  }
}tree;
struct road{
    int now;ll dis;
    road(int a,ll b){now=a,dis=b;}
    bool operator<(const road &rhs)const{return dis>rhs.dis;}
};
vector<road> g[maxn];
vector<ll> dis;
priority_queue<road>q;
void dijkstra(int st,int n=maxn-10){
  dis.resize(n+2);fill(all(dis),INF);
  q.emplace(st,0);dis[st]=0;
  while(!q.empty()){
    road t=q.top();q.pop();
    for(auto e:g[t.now]){
      ll cost=t.dis+e.dis;
      if(cost<dis[e.now]){
        dis[e.now]=cost;
        q.emplace(e.now,cost);
      }
    }
  }
}
int main() {IO;
	cin>>n>>m>>root;
  rep(i,1,m){
    int a,b,c;
    cin>>a>>b>>c;
    g[a].emplace_back(b,c);
    g[b].emplace_back(a,c);
  }
  dijkstra(root,n);
  tree.init(n+1);
  rep(i,1,n)for(auto e:g[i]){
    int to=e.now;
    if(dis[i]+e.dis==dis[to]) tree.add(i,to);
  }
  tree.maketree(root,n+1);
  tree.cal(root);
  int ans=0;
  rep(i,1,n)if(i!=root)ans=max(ans,tree.ans[i]);
  cout<<ans<<endl;
}

倍增灭绝树405 msAC

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define fi first
#define endl '\n'
#define se second
#define mp make_pair
#define pii pair<ll,ll>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
const int maxn=1e6+9,maxm=1e9+10,maxp=20;
const ll INF=1e18;
using namespace std;
int casn,n,m,k,root;
int cntin[maxn];
struct node{int to,next;};
class graph{public:
  node e[maxn];int head[maxn],nume;
  void init(int n=maxn-5){nume=0;fill_n(head,n+1,0);}
  void add(int a,int b){e[++nume]={b,head[a]};head[a]=nume;}
}inv,nxt,dom;
class domtree{public://@DAG@
  int deep[maxn],anc[maxn][maxp],que[maxn];
  vector<int>edge;
  void init(int n=maxn-5){
    inv.init(n),nxt.init(n),dom.init(n);
    edge.clear();
  }
  void bit(int &x,int h){
    for(int i=0;h>0;++i){
      if(h&1) x=anc[x][i];
      h>>=1;
    }
  }
  void add(int a,int b){nxt.add(a,b);inv.add(b,a);}
  int lca(int a,int b){
    if(deep[a]<deep[b]) swap(a,b);
    bit(a,deep[a]-deep[b]);
    if(a==b) return a;
    per(i,0,maxp-1) if(anc[a][i]!=anc[b][i])
      a=anc[a][i],b=anc[b][i];
    return anc[a][0];
  }
  void tpsort(int n){
    int tp=0,ed=0;
    rep(i,1,n) {
      if(!cntin[i]) {
        que[ed++]=i;
        inv.add(0,i);
        nxt.add(i,0);
        edge.push_back(i);
      }
    }
    while(ed!=tp){
      int now=que[tp++];
      forn(i,now,inv.head,inv.e){
        int to=inv.e[i].to;
        cntin[to]--;
        if(!cntin[to]) que[ed++]=to,edge.push_back(to);
      }
    }
  }
  void maketree(int n){
    tpsort(n);
    for(auto i:edge){
      int fa=-1;
      forn(j,i,nxt.head,nxt.e){
        int to=nxt.e[j].to;
        if(fa==-1) fa=to;
        else fa=lca(fa,to);
      }fa=fa==-1?0:fa;
      deep[i]=deep[fa]+1,anc[i][0]=fa;
      rep(j,1,maxp-1) anc[i][j]=anc[anc[i][j-1]][j-1];
      dom.add(fa,i);
    }
  }
  int ans[maxn];
  int cal(int now){
    ans[now]=1;
    forn(i,now,dom.head,dom.e) ans[now]+=cal(dom.e[i].to);
    return ans[now];
  }
}tree;
struct road{
    int now;ll dis;
    road(int a,ll b){now=a,dis=b;}
    bool operator<(const road &rhs)const{return dis>rhs.dis;}
};
vector<road> g[maxn];
vector<ll> dis;
priority_queue<road>q;
void dijkstra(int st,int n=maxn-10){
  dis.resize(n+2);fill(all(dis),INF);
  q.emplace(st,0);dis[st]=0;
  while(!q.empty()){
    road t=q.top();q.pop();
    for(auto e:g[t.now]){
      ll cost=t.dis+e.dis;
      if(cost<dis[e.now]){
        dis[e.now]=cost;
        q.emplace(e.now,cost);
      }
    }
  }
}
int main() {IO;
	cin>>n>>m>>root;
  rep(i,1,m){
    int a,b,c;
    cin>>a>>b>>c;
    g[a].emplace_back(b,c);
    g[b].emplace_back(a,c);
  }
  dijkstra(root,n);
  tree.init(n+1);
  rep(i,1,n)for(auto e:g[i]){
    int to=e.now;
    if(dis[i]+e.dis==dis[to]) {
      tree.add(to,i);
      ++cntin[to];
    }
  }
  tree.maketree(n+1);
  tree.cal(root);
  int ans=0;
  rep(i,1,n)if(i!=root)ans=max(ans,tree.ans[i]);
  cout<<ans<<endl;
}

 

posted @ 2019-08-01 16:25  nervending  阅读(226)  评论(0编辑  收藏  举报