table of Contents
Graph Theory
Minimum spanning tree
$ N $ city, $ M $ bars can repair the roads, and each road has a repair cost of $ w_i $, $ N $ to make the city connectivity, the required minimum cost?
It requires a minimum of $ N-1 $ edges form a tree.
## Kruskal algorithm prove
On top of $ n $ point and figure to do induction, prove that $ Kruskal $ $ n $ algorithm for any graph of order applies
Induction base
$ N = 1 $, apparently to find a minimum spanning tree
Induction process
example
P1550 [USACO08OCT] Watering Hole drilling
The idea is to build a super source to each point to build a side for the $ w_i $ right side, and then run the minimum spanning tree
Demonstrate how the product can be divided into a number of co-primes
Not write, I too dishes
Seeking the path points on the right side of the minimum spanning tree maximum
int f[N][20]; //i的第2^j祖先
int mn[N][20]; //i往上跳2^j祖先所经过的边的最小值
int query(int u,int v) {
int ans=inf;
if(dep[u]>dep[v]) swap(u,v);
for(int i=0,k=dep[v]-dep[u];i<=LG[k];++i)
if(k>>i&1) {
ans=min(ans,mn[v][i]);
v=f[v][i];
}
if(u==v) return ans;
for(int i=LG[dep[u]];i>=0;--i)
if(f[u][i]!=f[v][i]) {
ans=min(ans,min(mn[u][i],mn[v][i]));
u=f[u][i],v=f[v][i];
}
ans=min(ans,min(mn[u][0],mn[v][0]));
return ans;
}
kruskal reconstruction tree
orz lgj seniors, seniors turned out to be a blog
Shortest
SPFA forfeit ring
queue<int> q;
bool inq[N];
int dis[N], len[N];
bool spfa() { //返回值为true表示有负环 否则没有负环
fill(dis+1,dis+n+1,inf);
dis[1]=0,len[1]=1;
q.push(1);
inq[1]=true;
while(!q.empty()) {
int u=q.front() ; q.pop();
inq[u]=false;
for(int i=0;i<e[u].size();++i) {
int v=e[u][i];
int w=W[u][i];
if(dis[u]+w<dis[v]) {
dis[v]=dis[u]+w;
len[v]=len[u]+1;
if(len[v]>=n) return true;
if(!inq[v]) q.push(v),inq[v]=true;
}
}
}
return false;
}
Map building skills
By means of adding virtual points, etc. The problem is transformed
So as to achieve the purpose of reducing the number of equilateral.
Sao operation, long exposure
Topological sorting
In a $ the DAG $ directed acyclic graph), we vertices in the graph in a linear manner to sort, so that for any vertex $ U $ to $ V $ directed edge $ (u, v) $, are You may have front $ u $ in $ v $ of.
//拓扑排序 O(n^2)
int ind[N]; //每个点的入度
int seq[N],cnt; //求出的拓扑序
bool vis[N];
bool toposort() { //有环返回false
while(true) {
if(cnt==n) return true;
int k=0;
for(int i=1;i<=n;++i)
if(!vis[i]&&ind[i]==0) {
k=i; break;
}
if(k==0) return false;
seq[++cnt]=k; vis[k]=true;
for(int i=0;i<e[k].size();++i) {
int u=e[k][i];
--ind[u];
}
}
}
queue optimization
$O(n+m)$
//拓扑排序 O(n+m)
queue<int> q; //q中维护入度为0的点
int ind[N],seq[N],cnt;
bool toposort() { //有环返回false
for(int i=1;i<=n;++i)
if(!ind[i]) q.push(i);
while(!q.empty()) {
int u=q.front(); q.pop();
seq[++cnt]=u;
for(int i=0;i<e[u].size();++i) {
int v=e[u][i];
--ind[v];
if(ind[v]==0) q.push(v);
}
}
return cnt==n;
}
tarjian
int dfn[N],low[N],dfsclock;
int s[N],top;
int cnt; //当前联通块的编号
int bl[N]; //bl[i]表示i所在的强联通分量编号
vector<int> scc[N]; //scc[i]中存储编号为i强联通分量中的所有点
void dfs(int u) {
low[u]=dfn[u]=++dfsclock;
s[++top]=u;
for(int i=0;i<e[u].size();++i) {
int v=e[u][i];
if(dfn[v]) low[u]=min(low[u],dfn[v]);
else {
dfs(v);
low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u]) {
++cnt;
int v=s[top];
while(v!=u) {
bl[v]=cnt;
scc[cnt].push_back(v);
v=s[--top];
}
bl[u]=cnt;
scc[cnt].push_back(u);
}
}
## point reduction
In a strongly connected components as if the point is a big point, then, can become FIG directed acyclic graph (the DAG $ $), then what would facilitate the recursive
Differential Constraints
After write it, I feel that this is the right inequality set up a map ... I am too weak
Tree collar / group tree ring
We know that the tree is the most simple undirected graph connectivity.
There is only one path between any two points in the tree
Collar tree / tree cycloalkyl group: a tree Cato side.
One side is provided plus $ (u, v) $, $ u then made before, there is a path between v $, this edge after the addition of this path and this edge to form a ring.
This is also the only one of the rings is formed
We can put on view of the central ring, so that each point on the ring seems is a root.
The location is very important to find the ring
Similar approach $ noip2016 information transfer $
Get Tree ring base ring
Find the ring steps:
1. free to find a spot start as tree $ dfs $, and record each node access timestamp $ dfn $
2. $ dfs $ process there will be a point in $ dfn $ to even the edges than their smaller point, then this can be seen as plus side of that one. Record this edge $ (u, v) $
3. Violence Let $ u $ and $ v $ move up to the root, respectively, after recording their point.
4. They have been the deepest point of their $ lca $, $ u-> all points between lca $ + $ all points between v-> lca $ i.e. form a ring.
//求基环树中的环 方法一
int fa[N]; //f[i]为i在搜索树中的父亲结点
bool in[N],vis[N]; //表示i是否在环中
int cir[N],cnt;
int x,y;
void dfs(int u,int f) { //f为u的父亲结点
fa[u]=f; vis[u]=1;
for(int i=0 ;i<e[u].size();++i) {
int v=e[u][i];
if(v==f) continue;
if(vis[v]) x=u,y=v;
else dfs(v,u);
}
}
void solve() { //x到y一定是返祖边
dfs(1,0);
while(x!=y) {
cir[++cnt]=x;
x=fa[x];
}
cir[++cnt]=y;
}
//方法二
queue<int>q;
int deg[N],n;
void solve()
{
for(int i=1;i<=n;++i) in[i]=1;
for(int i=1;i<=n;++i)
if(deg[i]==1) q.push(i);
while(!q.empty())
{
int u=q.front();
q.pop();
int[u]=0;
for(int i=0;i<e[u].size();++i)
{
int v=e[u][i];
deg[v]--;
if(deg[v]==0) q.push(v);
}
}
int u;//u作为环的起点
for(u=1;u<=n;++u)
if(in[u]) break;
int v=u,las=0;//把u放环里
do{
cir[++cnt]=v;
int k;
for(i=0;i<e[v].size();++i)
{
k=e[v][i];
if(in[k] && k!=las) break;
}
la
v=k;
}while(v!=u)
}
Euler
By drawing lines one and only one passage through all the edges of all vertices is called the Euler path.
By drawing lines one and only one loop through all the edges of all vertices is called Euler.
FIG referred to as having Euler Euler FIG.
FIG passage having Euler called semi-Euler FIG.
There can be defined similarly to the time of FIG.
$ G $ is Euler if and only if $ G $ is odd and not vertices of communication.
$ G $ semi Euler if and only if $ $ G there are exactly two odd degree vertices.
certificate:
And no communication of odd vertices => there must be a ring
Then we delete the edge on the ring, the rest of the communication and still meets FIG no odd vertices
The connectivity rings may be a common point and to be put together
Snare loop algorithm
$ Dfs $ search, can not then go down (can not be reused an edge, but can be repeated after a point) will be back, recording path backtracking, backtracking is not clear mark on the side, and finally find out the path is the Euler .
To edge number with $ vis $ array record whether each side visited
//欧拉回路 圈套圈算法
struct edge
{
int v,nex,id;
};
bool vis[N];
int s[N],top;
int seq[N],cnt;
void dfs(int u)
{
s[++top]=u;
for(int i=head[u];i;i=e[i].nex)
{
if(vis[e[i].id]) continue;
vis[e[i].id]=true;
dfs(e[i].v);
}
--top;
seq[++top]=e[i].v;
}