codancer的圖論訓練(updating...)

2019.9.12

----580C.Kefa and Park
tags: 簡單DFS
code

----1081D.Maximum Distance
tags:帶點思維的MST,學會了只聯通某些點的並查集
code

2019.9.13

----1095F.Make It Connected
n2+mn^2+m條邊的MST,只需要考慮n+mn+m條即可。
code

----1037D. Valid BFS?
判斷給出的序列是否是合法的BFS序。
code

2019.9.25 (Hihocoder)

----1190.連通性四
點雙連通裸題,對每個邊分配點雙連通的id即可。

2019.9.26

51nod.1076.2條不相交的路徑
利用Tarjan求邊雙連通分量,對於在同一個分量中的點,則存在至少兩條不相交的路徑。
luogu.p1113雜物
簡單的拓撲排序,更新任務ii結束後的最晚時間即可。

2019.9.30

1228D. Complete Tripartite
判定給定的圖是否是可以分爲三個點集,使得任意兩個點集之間滿足完全二分關係。
sol:先把第一個點放到第一個點集中,然後和1不相連的也放到第一個點集中,以此類推找到三個集和。
1.如果有的點不在這三個點集中,則不能。
2.如果任意兩個點集之間不能滿足任意兩點有邊,則不能。
3.s1s2+s1s3+s2s3ms_1s_2+s_1s_3+s_2s_3 \neq m則不能,其中sis_i代表第ii個點集的大小。
code

2019.11.28

786B.Legacy
區間最短路經典題目,線段樹優化建圖。
code

#include<bits/stdc++.h>
 
using namespace std;
const int N = 5e5+100;
typedef long long ll;
const ll INF = (1e18);
//最短路部分
vector<pair<int,ll> > G[N];
ll dis[N];
bool vis[N];
void addedge(int u,int v,int w){
  G[u].push_back({v,w});
}
struct node{
  int id;
  ll d;
};
bool operator<(node a,node b){
  return a.d>b.d;
}
void dij(int s,int n){//起點爲s,總點數爲n的最短路
  priority_queue<node> q;
  for(int i=1;i<=n;i++){
    dis[i]=INF;vis[i]=0;
  }
  dis[s]=0;
  q.push({s,0});
  while(!q.empty()){
    node now=q.top();q.pop();
    int u=now.id;
    if(vis[u]) continue;
    vis[u]=1;
    for(auto V:G[u]){
      int v=V.first;
      ll w=V.second;
      if(dis[v]>dis[u]+w){
        dis[v]=dis[u]+w;
        q.push({v,dis[v]});
      }
    }
  }
}
 
int cnt;//總點數
struct Segment{
  int id[N*4];
  void buildtree(int rt,int l,int r,bool up){//建樹,判斷是上樹還是下數
    id[rt]=++cnt;
    if(l==r){
      int u=id[rt];
      int v=l;
      if(up) swap(u,v);
      addedge(u,v,0);//父子建邊
      return ;
    }
    int mid=(l+r)>>1;
    buildtree(rt<<1,l,mid,up);
    buildtree(rt<<1|1,mid+1,r,up);
    int u=id[rt];
    int v=id[rt<<1];
    if(up) swap(u,v);
    addedge(u,v,0);
    u=id[rt];
    v=id[rt<<1|1];
    if(up) swap(u,v);
    addedge(u,v,0);
  }
  void add_edge(int rt,int l,int r,int nl,int nr,int T,int w,bool up){//[nl,nr]<->T based on up
    if(nl<=l&&r<=nr){
      int u=id[rt];
      int v=T;
      if(up) swap(u,v);
      addedge(u,v,w);
      return ;
    }
    int mid=(l+r)>>1;
    if(nl<=mid) add_edge(rt<<1,l,mid,nl,nr,T,w,up);
    if(nr>mid) add_edge(rt<<1|1,mid+1,r,nl,nr,T,w,up);
  }
}UP,DOWN;
int main(){
  int n,q,s;
  cin>>n>>q>>s;
  cnt=n;
  UP.buildtree(1,1,n,1);
  DOWN.buildtree(1,1,n,0);
  int op,u,v,w,l,r;
  for(int i=1;i<=q;i++){
    cin>>op;
    if(op==1){
      cin>>u>>v>>w;
      addedge(u,v,w);
    }
    if(op==2){//v->[l,r] down爲true
      cin>>v>>l>>r>>w;
      DOWN.add_edge(1,1,n,l,r,v,w,1);
    }
    if(op==3){//[l,r]->x
      cin>>v>>l>>r>>w;
      UP.add_edge(1,1,n,l,r,v,w,0);
    }
  }
  dij(s,cnt);
  for(int i=1;i<=n;i++){
    if(dis[i]==INF) dis[i]=-1;
    if(i==1) cout<<dis[i];
    else cout<<' '<<dis[i];
  }
  cout<<endl;
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章