Bryce1010 / bryce1010-ACM-Template

人一我百,人十我万,追逐青春的梦想,怀着自信的心,永不放弃!by kuangbin (Bryce1010 ACM模板)
20 stars 3 forks source link

图论 #1

Open Bryce1010 opened 4 years ago

Bryce1010 commented 4 years ago

倍增及其应用 _ 未知作者

Bryce1010 commented 4 years ago

二分图与匹配 黄哲威

Bryce1010 commented 4 years ago

浅谈一些树形问题 -- 高胜寒

树的遍历

宽度优先

深度优先


- 后序遍历

### 树的存储
- 邻接表
- 有根树记录所有孩子
- 有根树记录父亲节点
- DFS 序

### 树问题的应用
#### 树形动态规划
- 将一棵树原问题转化为其子树上问题
- 为每一个子树计算其最优值
- 将最优值合并至有根树  

- [ ] SPOJ/MTREE

#### 最近公共祖先
5种写法
- 暴力算法
- 倍增算法
- dfs序算法
- targan算法
- 树链剖分算法
> 将一颗树剖成若干条链
> 每一个点到根都只经过log级别条链
> 对于每条链当做数列来做 

![image](https://user-images.githubusercontent.com/30361513/78781691-46234b80-79d3-11ea-89ac-683ffa2b0b9d.png)
- [ ] SPOJ/ QTREE2
- [ ] SPOJ OTOCI
- [ ] SPOJ COT
- [ ] SPOJ MINDIST  

#### DFS序+数据结构  

#### 树链剖分   

#### 动态树   
- 动态维护一种剖分
- 类别树链剖分
- 使用SPLAY维护动态树

#### 其他

### 总结
根据题意, 判断是哪一类树形问题, 具体问题具体分析
对于每一种类型的题目找出相应的解法

> 若需求路径上的问题, 优先考虑LCA法, 其次考虑dfs序, 最后树链剖分;
> 首选找出树与图所不同的地方, 将题目转化为一些其他模型的问题;
Bryce1010 commented 4 years ago

浅析二分图匹配在信息学竞赛中的应用_王俊

Bryce1010 commented 4 years ago

生成树和拓扑排序_黄哲威

并查集


int fa[maxn];
int getroot(int x){
    return x==fa[x]?x:getroot(fa(x));
}

void merge(int x,int y){
    int p=getroot(x),q=getroot(y);
    fa[p]=q;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i)
        fa[i]=i;
    return 0;
}

并查集优化- 路径压缩


int fa[maxn];
int getroot(int x){
    return x==fa[x]?x:fa[x]=getroot(fa(x));
}

void merge(int x,int y){
    int p=getroot(x),q=getroot(y);
    fa[p]=q;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i)
        fa[i]=i;
    return 0;
}

并查集优化- 按秩合并

深度更小的树指向深度更大的树

int fa[maxn],h[maxn]; int getroot(int x){ return x==fa[x]?x:getroot(fa(x)); }

void merge(int x,int y){ int p=getroot(x),q=getroot(y); if(h[p]>h[q])swap(p,q); fa[p]=q;h[q]++; } int main(){ cin>>n; for(int i=1;i<=n;++i) fa[i]=i; return 0; }

### 生成树  

#### Kruskal
```cpp
int n,m,ans;
struce edge{
    u,v,w;
}e[M];

bool cmp(edge a, edge b){
    return a.w<b.w;
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=m;++i){
        cin>>e[i].u>>e[i].v>>e[i].w;
    }
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;++i){
        int p=getroot(e[i].u),q=getroot(e[i].v]);
        if(p!=q){
            fa[p]=q;
            ans+=e[i].w;
        }
    }
    return 0;
}

Prim 算法

拓扑排序

int top,q[N];

int main(){
    cin>>n>>m;
    for(int i=1;i<=m;++i){
        int u,v;
        cin>>u>>v;
        e[u].push_back(v);
        d[v]++;
    }
    for(int i=1;i<=n;++i)
        if(!d[i])
            q[++top]=i;
    while(top){
        int u=q[top];top--;
        for(int i=0;i<e[u].size();++i){
            int v=e[u][i];
            d[v]--;
            if(!d[v])
                q[++top]=v;
        }
    }    
    return 0;
}
Bryce1010 commented 4 years ago

图论复习 _ 未知作者

图的存储形式:

传递闭包

最小生成树

二分图匹配

Bryce1010 commented 4 years ago

图论入门与最短路 _ 黄哲威

#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
vector<pa>v;
int main(){
    for(int i=1;i<=10;++i)
        v.push_back(make_pair(rand(),i));
    sort(v.begin(),v.end());
    for(int i=0;i<v.size();++i)
        cout<<v[i].first<<' '<<v[i].second<<endl;
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

priority_queue<int,vector<int>,greater<int> >q; //小根堆  
int main(){
    for(int i=1;i<=10;++i)
        q.push(rand());
    for(int i=1;i<=10;++i){
        cout<<q.top()<<endl;
        q.pop();
    }
    return 0;
}

vectore[N];

int main(){ cin>>n>>m; for(int i=1;i<=m;++i){ int u,v; cin>>u>>v; e[u].push_back(v); e[v].push_back(u); } return 0; }

- 图的bfs遍历
```python
void bfs(int x){
    int head=0,tail=1;
    q[0]=x;vis[x]=1;
    while(head!=tail){
        int u=q[head];head++;
        for(int i=0;i<E[u].size();++i){
            int v=e[u][i];
            if(!vis[v]){
                vis[v]=1;
                dis[v]=dis[u]+1;
                q[tail++]=v;
            }
        }
    }
}

void dfs(int x){ vis[x]=1; for(int i=0;i<e[x].size();++i){ if(!vis[x][i]) dfs(e[x][i]); } }


### 最短路  
- Floyd算法 
F[k, i, j] 表示经过k个点, i到j的最短路;   
F[k, i ,j] = F[k-1, i, k] + F[k-1, k , j]  
通过省略一维空间: 
F[i,j] = F[i, k] + F[k , j]
```python
void floyd(){
    for(int k=1;k<=n;++k){
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
}
Bryce1010 commented 4 years ago

图论知识及其应用

Bryce1010 commented 4 years ago

树分治_黄哲威

Bryce1010 commented 4 years ago

树链剖分_蒋一瑶

Bryce1010 commented 4 years ago

树上倍增_黄哲威

Bryce1010 commented 4 years ago

图论_李煜东

图的遍历

最短路问题

Floyd算法

可以经过标号<=k的点中转时, 从i到j的最短路
F[k,i,j]=min{ F[k-1,i,k]+F[k-1,k,j]} F[i,j]=min{F[k-1,i,k]+F[k-1,k,j]| O(n^3) k->i->j

Dijkstra 算法

普通: O(n^2)
堆优化: O(NlogN)~O(MlogN)

Bellman-Ford算法

BF算法: O(N^2) SPFA算法: 队列优化的BF算法; 稀疏图上O(kN), 稠密图上O(N^2) 可以应用于负权图

最小生成树

Kruskal

O(MlogN) 利用并查集, 起初每个点构成一个集合 所有边按照边权从小到大排序, 一次扫描 如果当前扫描得到边连接连个不同的集合, 合并

Prim

O(N^2) 以任一点为基准点, 将节点分为两组:

树上的倍增法

LCA

二分图

二分图匹配

最大匹配

增广路算法(匈牙利算法)

最小点覆盖

Bryce1010 commented 4 years ago

图论知识及其应用

Bryce1010 commented 4 years ago

图论专题生成树_唐文斌

Bryce1010 commented 4 years ago

网络流_未知作者

Bryce1010 commented 4 years ago

网络流_魏越闽

Bryce1010 commented 4 years ago

网络流_周津浩&黄着威

Bryce1010 commented 4 years ago

网络流建模 周尚彦

Bryce1010 commented 4 years ago

线性规划与网络流_曹钦翔

Bryce1010 commented 4 years ago

2-SAT问题_未知作者