链式前向星是一种存储图的数据结构,顾名思义,链式前向星使用链表的方式存储图的边、点、权。
利用数组实现,需要head[],nextt[],to[],idx。head用以记录节点的第一条边的编号,nextt用来存储下一条边的编号,to用来存储当前边的终点。
代码实现建图:
void add(int u,int v){
to[++idx]=v;
nextt[idx]=head[u];
head[u]=idx;
}
若要加权就多定义一个存储权的数组:
void add(int u,int v,int c){
to[++idx]=v;
w[idx]=c;
nextt[idx]=head[u];
head[u]=idx;
}
图的遍历:
如果要遍历一个点所连的边,就从head开始,每次取nextt,直到为空
for(int i=head[k];i;i=nextt[i])
当然,链式前向星也可以使用结构体实现:
void add(int u,int v,int c){
idx++;
e[idx].to=v;
e[idx].w=c;
e[idx].next=head[u];
head[u]=idx;
}
还有最方便的方法——vector
vector相对于那两种方法空间灵活,并且也不用麻烦地去手动维护链表
定义
vector<vector<int> > e(100);
加边
e[u].push_back(v);
带权
vector<vector<pair<int,int> > > e(100);
实战
1.模版题
输入n(点数),m(边数),flag(flag==1为有向,否则无向)
然后输入每条边的起点终点和权
输出每个点所连的边的终点和权
若flag为0,即无向图时,只需再反向建一次边就可以达到无向图的效果
最后遍历输出
#include<bits/stdc++.h>
using namespace std;
vector < vector < pair<int,int> > > e(2000005);
int n,m,x,y,z;
bool flag;
int main(){
cin>>n>>m>>flag;
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
e[x].push_back(make_pair(y,z));
if(!flag){
e[y].push_back(make_pair(x,z));
}
}
for(int i=1;i<=m;i++){
for(int j=e[i].size()-1;j>=0;j--){
cout<<i<<' '<<e[i][j].first<<' '<<e[i][j].second<<endl;
}
if(!e[i].size()){
cout<<endl;
}
}
return 0;
}
2.树
此题给定一棵树和s,求多少条路径总和为s
使用DFS
#include<bits/stdc++.h>
using namespace std;
vector < vector < int > > e(100005);
int n,m,x,y,ans,z;
int a[100005],dep[100005];
void search(int k){
if(dep[k]==m){
ans++;
return ;
}
for(int i=0;i<e[k].size();i++){
int xx=e[k][i];
dep[xx]=dep[k]+a[xx];
if(dep[xx]>m){
continue;
}
if(dep[xx]==m){
ans++;
continue;
}
search(xx);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
while(cin>>x>>y&&x!=EOF){
z++;
e[x].push_back( y );
}
for(int i=1;i<=n;i++){
dep[1]=a[i];
search(i);
}
cout<<ans;
return 0;
}
3.Tree Cutting
给定一棵
N
N
N 个节点的 无根树 。现在要找到所有的节点,使得删除这个节点之后,剩余的所有连通块中最大连通块的大小
<
=
<=
<=
N
/
2
N/2
N/2
即树的重心
DFS 来找出每个节点的儿子,然后算出以每个节点为根的子树的大小,再枚举牛棚检查是否可以。
#include<bits/stdc++.h>
using namespace std;
vector < vector < int > > e(100005),b(100005);
int n,m,x,y,ans,z;
int sz[100005];
bool flag1,flag2;
void search(int u,int fa){
sz[u]=1;
for(int i=0;i<e[u].size();i++){
if(e[u][i]==fa){
continue;
}
search(e[u][i],u);
b[u].push_back(e[u][i]);
sz[u]+=sz[e[u][i]];
}
}
int main(){
cin>>n;
for(int i=1;i<n;i++){
cin>>x>>y;
e[x].push_back( y );
e[y].push_back( x );
}
search(1,-1);
for(int i=1;i<=n;i++){
flag2=0;
for(int j=0;j<b[i].size();j++){
z=b[i][j];
if(sz[z]>n/2){
flag2=1;
break;
}
}
if(sz[i]>=n/2&&!flag2){
cout<<i<<endl;
flag1=1;
}
}
if(!flag1){
cout<<"NONE";
}
return 0;
}