2019.9.12
----580C.Kefa and Park
tags: 简单DFS
code
----1081D.Maximum Distance
tags:带点思维的MST,学会了只联通某些点的并查集
code
2019.9.13
----1095F.Make It Connected
n
2
+
m
n^2+m
n2+m条边的MST,只需要考虑
n
+
m
n+m
n+m条即可。
code
----1037D. Valid BFS?
判断给出的序列是否是合法的BFS序。
code
2019.9.25 (Hihocoder)
----1190.连通性四
点双连通裸题,对每个边分配点双连通的id即可。
2019.9.26
—51nod.1076.2条不相交的路径
利用Tarjan求边双连通分量,对于在同一个分量中的点,则存在至少两条不相交的路径。
—luogu.p1113杂物
简单的拓扑排序,更新任务
i
i
i结束后的最晚时间即可。
2019.9.30
—1228D. Complete Tripartite
判定给定的图是否是可以分为三个点集,使得任意两个点集之间满足完全二分关系。
sol:先把第一个点放到第一个点集中,然后和1不相连的也放到第一个点集中,以此类推找到三个集和。
1.如果有的点不在这三个点集中,则不能。
2.如果任意两个点集之间不能满足任意两点有边,则不能。
3.
s
1
s
2
+
s
1
s
3
+
s
2
s
3
≠
m
s_1s_2+s_1s_3+s_2s_3 \neq m
s1s2+s1s3+s2s3=m则不能,其中
s
i
s_i
si代表第
i
i
i个点集的大小。
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;
}