I. Definition of Graph
Graph consists of two sets, one is a non-empty but finite vertex set V, and the other is a set E describing the relational edges between sets.
Therefore, a graph can be expressed as G=(V,E). Each edge is a pair of vertices (v,w) and v,w < V.
Usually | V | and | E | denote the number of vertices and the number of edges. The vertex of a graph must not be empty, but the edge can be empty.
II. Terminology Relevant to Graph
Undirected graph
Adjacent Points: If <v.w> is any edge in an undirected graph. Then V and W are adjacent points. if < v, w > is any edge of a digraph, then V adjacent to W is called
Path, simple path, loop, no loop:
Path of a path in the graph refers to a sequence of vertices: v1,v2....vn. Any two adjacent vertices in the sequence can find the corresponding edges in the graph. The length of a path is the number of edges contained in the path.
A simple path means that all vertices are different except the first vertex of the path. A loop of a digraph, also known as a ring, refers to a path v1=vn. If there is no loop in a digraph, it is called acyclic graph. For undirected graphs, the minimum number of vertices constituting a loop is 3.
The degree of vertex v refers to the number of edges attached to the vertex. Vertices in a digraph are divided into degrees of entry and degrees of exit. In-degree of vertex v refers to the number of edges with vertex v as the end point. The out-degree of vertex v refers to the number of edges starting from vertex v.
Power and Network: Attach some data information to the edge. This information is usually called weight or cost. Graphs with weights on edges are called network graphs or networks.
Subgraph: For graphs G=(V,E) and G1=(V1,E1). If V1 is a subset of V and E1 is a subset of E, then G1 is a subgraph of G.
Spanning Tree and Spanning Forest: The spanning tree of a connected graph G is a minimal connected subgraph of G containing n vertices. It must contain n-1 edges, and spanning trees are not unique. When graph G is a tree if and only if G satisfies one of the following four conditions:
G has n-1 edges and no rings.
G has n-1 edges and G is connected.
Each vertex in G has and only one path connected.
G is connected, but deleting any edge will make it disconnected.
Generating forests: Because every connected component in a disconnected graph is a minimal connected subgraph. That is, a spanning tree can correspond to a connected component. All these connected components of the spanning tree constitute the forest.
3. Operation of Graphs
1. Storage
1 #include<iosrteam> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing{ 10 const int N=20005,M=100005; 11 int n,m,last[N],cnt; 12 struct node{ 13 int to,dis,nxt; 14 }edge[M<<1]; 15 void add(int from,int to,int dis){ 16 edge[++cnt].to=to,edge[cnt].dis=dis,edge[cnt].nxt=last[from],last[from]=cnt; 17 } 18 struct main{ 19 main(){ 20 n=read();int x,y,z; 21 for(int i=1;i<=m;i++){ 22 x=read(),y=read(),z=read(); 23 add(x,y,z),add(y,x,z); 24 } 25 exit(0); 26 } 27 int read(){ 28 int x=0,f=1; 29 char ch=getchar(); 30 while(!isdigit(ch)){ 31 if(ch=='-') f=-1; 32 ch=getchar(); 33 } 34 while(isdigit(ch)){ 35 x=x*10+ch-'0',ch=getchar(); 36 } 37 return x*f; 38 } 39 }UniversalLove; 40 } 41 int main(){ 42 Moxing::main(); 43 }
2. Traversal
1 void dfs(int x){ 2 vis[x]=1; 3 for(int i=last[x];i;i=edge[i].nxt){ 4 int y=edge[i].to; 5 if(vis[y]) continue ; 6 dfs(y); 7 } 8 }
1 void bfs(){ 2 fill(deep+1,deep+1+n,0);deep[1]=1; 3 queue<int>q; 4 q.push(1); 5 while(!q.empty()){ 6 int x=q.front(),q.pop(); 7 for(int i=last[x];i;i=edge[i].nxt){ 8 int y=edge[i].to; 9 if(deep[y]) continue ; 10 deep[y]=deep[x]+1; 11 q.push(y); 12 } 13 } 14 }
III. Trees
1. Tree Chain Splitting
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing{ 10 const int N=20005,M=100005; 11 int n,m,last[N],cnt; 12 struct node{ 13 int to,dis,nxt; 14 }edge[M<<1]; 15 void add(int from,int to,int dis){ 16 edge[++cnt].to=to,edge[cnt].dis=dis,edge[cnt].nxt=last[from],last[from]=cnt; 17 } 18 struct main{ 19 main(){ 20 n=read();int x,y,z; 21 for(int i=1;i<=m;i++){ 22 x=read(),y=read(),z=read(); 23 add(x,y,z),add(y,x,z); 24 } 25 exit(0); 26 } 27 int read(){ 28 int x=0,f=1; 29 char ch=getchar(); 30 while(!isdigit(ch)){ 31 if(ch=='-') f=-1; 32 ch=getchar(); 33 } 34 while(isdigit(ch)){ 35 x=x*10+ch-'0',ch=getchar(); 36 } 37 return x*f; 38 } 39 }UniversalLove; 40 } 41 int main(){ 42 Moxing::main(); 43 }
2. Diameter of trees
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing { 10 //Definition of tree diameter:The longest path on a tree 11 const int N=1e5+5; 12 int last[N],cnt; 13 struct node { 14 int to,nxt,dis; 15 } edge[N<<1]; 16 void add(int from,int to,int dis) { 17 edge[++cnt].to=to; 18 edge[cnt].dis=dis; 19 edge[cnt].nxt=last[from]; 20 last[from]=cnt; 21 } 22 int p,q,fa[N],d[N],ans; 23 bool vis[N]; 24 //d[x]:from x Node departure direction X The farthest node distance that a root subtree can reach 25 //d[x]=max(d[x],d[y]+edge[i].dis); 26 void dp(int x) { 27 vis[x]=1; 28 for(int i=last[x]; i; i=edge[i].nxt) { 29 int y=edge[i].to; 30 if(vis[y]) continue ; 31 dp(y); 32 ans=max(ans,d[x]+d[y]+edge[i].dis); 33 d[x]=max(d[x],d[y]+edge[i].dis); 34 } 35 } 36 //Starting from any node, the node farthest away from the starting point is determined as p 37 //slave nodes p Start, go through it again, and find out p The farthest node is marked as q 38 void dfs(int x) { 39 for(int i=last[x]; i; i=edge[i].nxt) { 40 int y=edge[i].to; 41 if(fa[x]==y) continue; //If you don't go back, you can also recurse the father node and omit it. fa Array space 42 fa[y]=x; 43 d[y]=d[x]+edge[i].dis; //The longest path of the current node 44 dfs(y); 45 } 46 } 47 struct main { 48 main() { 49 int n; 50 scanf("%d",&n); 51 for(int i=1; i<=n; i++) fa[i]=i; 52 for(int i=1; i<=n-1; i++) { 53 int x,y,cost; 54 scanf("%d%d%d",&x,&y,&cost); 55 add(x,y,cost); 56 add(y,x,cost); 57 } 58 dfs(1); 59 int ansmax=0,ansindix=0; 60 for(int i=1; i<=n; i++) { 61 if(d[i]>ansmax) ansmax=d[i],ansindix=i; 62 d[i]=0; 63 fa[i]=i; 64 } 65 dfs(ansindix); 66 for(int i=1; i<=n; i++) { 67 cout<<d[i]<<' '; 68 } 69 cout<<endl; 70 //d[x]:from x Node departure direction X The farthest node distance that a root subtree can reach 71 //d[x]=max(d[x],d[y]+edge[i].dis); 72 memset(d,0,sizeof(d)); 73 dp(1); 74 for(int i=1; i<=n; i++) { 75 cout<<d[i]<<' '; 76 } 77 cout<<endl<<ans; 78 exit(0); 79 } 80 } UniversalLove; 81 } 82 int main() { 83 Moxing::main(); 84 }
3. Center of gravity of trees
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing { 10 //Definition: if point u All subtrees of rooted trees (excluding the whole tree) are no larger than half of the total number of nodes.,Call point u Focus. 11 //Nature: 12 //1.The center of gravity must exist. 13 //2.The minimum distance from a point in the tree to the center of gravity. 14 //3.The tree adds or deletes a leaf, and the center of gravity moves the distance of at most one edge. 15 //4.Connect two trees through one side to form a new tree. The center of gravity must be on the path connecting the center of gravity of two trees. 16 const int N=1e5+5; 17 int last[N<<1],cnt; 18 struct node { 19 int to,nxt,dis; 20 } edge[N<<1]; 21 void add(int from,int to,int dis) { 22 edge[++cnt].to=to; 23 edge[cnt].dis=dis; 24 edge[cnt].nxt=last[from]; 25 last[from]=cnt; 26 } 27 int size[N],mx[N],rt=1,n; 28 bool vis[N]; 29 //mx[x]Representation deletion x The size of the largest subtree after a node 30 void root(int x,int fa) { 31 size[x]=1; 32 mx[x]=0; 33 for(int i=last[x]; i; i=edge[i].nxt) { 34 int y=edge[i].to; 35 if(!vis[y]&&y!=fa) { 36 root(y,x); 37 size[x]+=size[y]; 38 mx[x]=max(mx[x],size[y]); 39 } 40 } 41 mx[x]=max(mx[x],n-size[x]); 42 if(mx[x]<mx[rt]) rt=x; 43 } 44 struct main { 45 main() { 46 scanf("%d",&n); 47 for(int i=1; i<=n-1; i++) { 48 int x,y,cost; 49 scanf("%d%d%d",&x,&y,&cost); 50 add(x,y,cost); 51 add(y,x,cost); 52 } 53 root(1,1); 54 cout<<rt; 55 exit(0); 56 } 57 } UniversalLove; 58 } 59 int main() { 60 Moxing::main(); 61 }
4. Recent Public Ancestors
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing{ 10 //fa[x][k]: x 2^k Ancestors fa[x][k]=fa[fa[x][k-1]][k-1] 11 const int N=5e5+5,M=20; 12 int last[N],cnt,n,m,s,t,deep[N]; 13 struct node { 14 int to,nxt; 15 } edge[N<<1]; 16 void add(int from,int to) { 17 edge[++cnt].to=to; 18 edge[cnt].nxt=last[from]; 19 last[from]=cnt; 20 } 21 struct nod{ 22 int fa; 23 }f[N][M]; 24 void dfs(int x){ 25 for(int i=last[x];i;i=edge[i].nxt){ 26 int y=edge[i].to; 27 if(deep[y]) continue ; 28 deep[y]=deep[x]+1; 29 f[y][0].fa=x; 30 dfs(y); 31 } 32 } 33 void cal(){ 34 for(int i=1;i<=t;i++){ 35 for(int j=1;j<=n;j++){ 36 f[j][i].fa=f[f[j][i-1].fa][i-1].fa; 37 } 38 } 39 } 40 int lca(int x,int y){ 41 if(deep[y]>deep[x]) swap(x,y); 42 for(int i=t;i>=0;i--){ 43 if(deep[f[x][i].fa]>=deep[y]) x=f[x][i].fa; 44 } 45 if(x==y) return x; 46 for(int i=t;i>=0;i--){ 47 if(f[x][i].fa!=f[y][i].fa){ 48 x=f[x][i].fa,y=f[y][i].fa; 49 } 50 } 51 return f[x][0].fa; 52 } 53 struct main{ 54 main(){ 55 scanf("%d%d%d",&n,&m,&s);t=log(n)/log(2)+1; 56 for(int i=1;i<=n-1;i++){ 57 int x,y; 58 scanf("%d%d",&x,&y); 59 add(x,y); 60 add(y,x); 61 } 62 deep[s]=1;f[s][0].fa=s; 63 dfs(s); 64 cal(); 65 while(m--){ 66 int x,y; 67 scanf("%d%d",&x,&y); 68 printf("%d\n",lca(x,y)); 69 } 70 exit(0); 71 } 72 }UniversalLove; 73 } 74 int main(){ 75 Moxing::main(); 76 }
5. Minimum Spanning Tree
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing{ 10 const int N=1e5+5; 11 struct node{ 12 int from,to,dis; 13 }E[N<<1]; 14 int n,m,fa[N],ans; 15 bool cmp(node a,node b){ 16 return a.dis<b.dis; 17 } 18 int get(int x){ 19 if(x==fa[x]) return x; 20 return fa[x]=get(fa[x]); 21 } 22 void kruskal(){ 23 for(int i=1;i<=n;i++){ 24 fa[i]=i; 25 } 26 sort(E+1,E+1+m,cmp); 27 for(int i=1;i<=m;i++){ 28 int x=get(E[i].from),y=get(E[i].to); 29 if(x==y) continue ; 30 fa[x]=y; 31 ans+=E[i].dis; 32 } 33 } 34 struct main{ 35 main(){ 36 scanf("%d%d",&n,&m); 37 for(int i=1;i<=m;i++){ 38 scanf("%d%d%d",&E[i].from,&E[i].to,&E[i].dis); 39 } 40 kruskal(); 41 printf("%d\n",ans); 42 exit(0); 43 } 44 }UniversalLove; 45 } 46 int main(){ 47 Moxing::main(); 48 }
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing { 10 int n,m,a[5005][5005],d[5005],ans; 11 bool vis[5005]; 12 void prim() { 13 // memset(vis,0,sizeof(vis)); 14 memset(d,0x3f,sizeof(d));d[1]=0; 15 for(register int k=2; k<=n; k++) { 16 int x=0; 17 for(register int i=1; i<=n; i++) { 18 if(!vis[i]&&(x==0||d[i]<d[x])) { 19 x=i; 20 } 21 } 22 vis[x]=1;//cout<<x<<' '; 23 for(register int i=1; i<=n; i++) { 24 if(!vis[i]) d[i]=min(d[i],a[x][i]); 25 //cout<<d[i]<<' '; 26 } 27 } 28 } 29 struct main{ 30 main(){ 31 scanf("%d%d",&n,&m); 32 memset(a,0x3f,sizeof(a)); 33 for(int i=1;i<=n;i++) a[i][i]=0; 34 for(int i=1;i<=m;i++){ 35 int x,y,z; 36 scanf("%d%d%d",&x,&y,&z); 37 a[y][x]=a[x][y]=min(a[x][y],z); 38 } 39 prim(); 40 for(int i=2;i<=n;i++) ans+=d[i]; 41 printf("%d\n",ans); 42 exit(0); 43 } 44 }UniversalLove; 45 } 46 int main(){ 47 Moxing::main(); 48 }
6. Sub-small spanning tree
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing { 10 #define inf 2333333333333333; 11 const int M=2e5+5; 12 const int N=1e5+5; 13 int n,m,last[N],cnt,fa[N],deep[N],t; 14 bool pd[N]; 15 struct node { 16 int from,to,nxt; 17 long long dis; 18 } E[M],edge[M<<1]; 19 bool cmp(node a,node b) { 20 return a.dis<b.dis; 21 } 22 int get(int x) { 23 if(x==fa[x]) return x; 24 return fa[x]=get(fa[x]); 25 } 26 void add(int from,int to,long long dis) { 27 edge[++cnt].from=from; 28 edge[cnt].to=to; 29 edge[cnt].dis=dis; 30 edge[cnt].nxt=last[from]; 31 last[from]=cnt; 32 } 33 struct nod { 34 int fa; 35 long long maxx,minn; 36 } f[N][19]; 37 void dfs(int x,int fa) { 38 f[x][0].fa=fa; 39 for(int i=last[x]; i; i=edge[i].nxt) { 40 int y=edge[i].to; 41 if(y==fa) continue ; 42 f[y][0].fa=x; 43 f[y][0].maxx=edge[i].dis; 44 f[y][0].minn=-inf; 45 deep[y]=deep[x]+1; 46 dfs(y,x); 47 } 48 } 49 void cal() { 50 for(int i=1; i<=t; i++) { 51 for(int j=1; j<=n; j++) { 52 f[j][i].fa=f[f[j][i-1].fa][i-1].fa; 53 f[j][i].maxx=max(f[j][i-1].maxx,f[f[j][i-1].fa][i-1].maxx); 54 f[j][i].minn=max(f[j][i-1].minn,f[f[j][i-1].fa][i-1].minn); 55 if(f[j][i-1].maxx>f[f[j][i-1].fa][i-1].maxx) f[j][i].minn=max(f[j][i].minn,f[f[j][i-1].fa][i-1].maxx); 56 else if(f[j][i-1].maxx<f[f[j][i-1].fa][i-1].maxx) f[j][i].minn=max(f[j][i].minn,f[j][i-1].maxx); 57 } 58 } 59 } 60 int lca(int x,int y) { 61 if(deep[x]<deep[y]) swap(x,y); 62 for(int i=t; i>=0; i--) { 63 if(deep[f[x][i].fa]>=deep[y]) x=f[x][i].fa; 64 } 65 if(x==y) return x; 66 for(int i=t; i>=0; i--) { 67 if(f[x][i].fa!=f[y][i].fa) { 68 x=f[x][i].fa; 69 y=f[y][i].fa; 70 } 71 } 72 return f[x][0].fa; 73 } 74 long long query(int x,int y,long long dis) { 75 long long ans=-inf; 76 for(int i=t; i>=0; i--) { 77 if(deep[f[x][i].fa]>=deep[y]) { 78 if(dis!=f[x][i].maxx) ans=max(ans,f[x][i].maxx); 79 else ans=max(ans,f[x][i].minn); 80 x=f[x][i].fa; 81 } 82 } 83 return ans; 84 } 85 void kruskal() { 86 for(int i=1; i<=n; i++) { 87 fa[i]=i; 88 } 89 sort(E+1,E+1+m,cmp); 90 long long ans=0; 91 for(int i=1; i<=m; i++) { 92 int x=get(E[i].from),y=get(E[i].to),dis=E[i].dis; 93 if(x==y) continue ; 94 fa[x]=y; 95 ans+=dis; 96 pd[i]=1; 97 add(E[i].to,E[i].from,dis); 98 add(E[i].from,E[i].to,dis); 99 } 100 } 101 struct main { 102 main() { 103 scanf("%d%d",&n,&m); 104 t=log(n)/log(2)+1; 105 for(int i=1; i<=m; i++) { 106 scanf("%d%d%lld",&E[i].from,&E[i].to,&E[i].dis); 107 } 108 f[1][0].minn=-inf; 109 deep[1]=1; 110 dfs(1,-1); 111 cal(); 112 long long res=inf; 113 for(int i=1; i<=m; i++) { 114 if(!pd[i]) { 115 int x=E[i].from,y=E[i].to,anc=lca(x,y); 116 long long dis=E[i].dis; 117 long long maxx=query(x,anc,dis),maxy=query(y,anc,dis); 118 res=min(res,ans-max(maxx,maxy)+dis); 119 } 120 } 121 printf("%lld\n",res); 122 exit(0); 123 } 124 } UniversalLove; 125 } 126 int main() { 127 Moxing::main(); 128 }
kruskal algorithm has been proved that for any u,v has a maximum value of the edge weight between u and v which is less than or equal to the edge weight of the un-selected edge between u and v.
Unstrict sub-spanning tree: traverse each unselected edge (u,v,d) and replace it with the largest edge between u and V
The large value of the deposit order removes the case that the unselected edge right is equal to the original edge right, and only retains less than.