2019.9.12
----580C.Kefa and Park
tags: 簡單DFS
code
----1081D.Maximum Distance
tags:帶點思維的MST,學會了只聯通某些點的並查集
code
2019.9.13
----1095F.Make It Connected
條邊的MST,只需要考慮條即可。
code
----1037D. Valid BFS?
判斷給出的序列是否是合法的BFS序。
code
2019.9.25 (Hihocoder)
----1190.連通性四
點雙連通裸題,對每個邊分配點雙連通的id即可。
2019.9.26
—51nod.1076.2條不相交的路徑
利用Tarjan求邊雙連通分量,對於在同一個分量中的點,則存在至少兩條不相交的路徑。
—luogu.p1113雜物
簡單的拓撲排序,更新任務結束後的最晚時間即可。
2019.9.30
—1228D. Complete Tripartite
判定給定的圖是否是可以分爲三個點集,使得任意兩個點集之間滿足完全二分關係。
sol:先把第一個點放到第一個點集中,然後和1不相連的也放到第一個點集中,以此類推找到三個集和。
1.如果有的點不在這三個點集中,則不能。
2.如果任意兩個點集之間不能滿足任意兩點有邊,則不能。
3.則不能,其中代表第個點集的大小。
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;
}