邻接矩阵
容易存储,修改,处理重边和查询。但是对于稀疏图来说非常非常浪费空间
dp:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int t,ans;
int a[205],g[205][205],pre[205],f[205];
void print(int x){
if (pre[x]==0){
printf("%d",x);
return;
}
print(pre[x]);
printf(" %d",x);
}
int main(){
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%d",&a[i]);
int x;
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
scanf("%d",&x);
if(x)g[i][j]=1;//注意题干是单向边i->j
}//邻接表存图
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){//遍历父节点
if(g[j][i]&&f[j]>f[i]){
f[i]=f[j];//dp,f[i]为以第i个节点结束的最大值
pre[i]=j;
}
}
f[i]+=a[i];//父节点+=子节点
if (f[i]>ans) {
ans=f[i];
t=i;
}
}
print(t);
printf("\n%d",ans);
return 0;
}
邻接表
当点数大于1000的时候,我们无法使用二维数组进行存储,故考虑不定长数组vector,但有时我们需要将到达的点和权值一起存入,故需要结构体。
set存子节点:
//选一个好的数据结构很重要
//只有c++11能通过编译
#include<bits/stdc++.h>
using namespace std;
int n,m;
set<int> e[100009];//默认从小到大
bool vis[100009];
void init(){
int u=0,v=0;
for(scanf("%d%d",&n,&m);m;--m){
scanf("%d%d",&u,&v);
e[u].insert(v);
}
}
void dfs(int x=1){
if(vis[x])return;
vis[x]=1;
printf("%d ",x);
for(int v:e[x])dfs(v);
}
void bfs(){
queue<int>q;
q.push(1);
while(!q.empty()){
int x=q.front();q.pop();
if(vis[x])continue;vis[x]=1;
printf("%d ",x);
for(int v:e[x])q.push(v);
}
}
int main(){
init();
dfs();
putchar('\n');
memset(vis,0,sizeof(vis));
bfs();
putchar('\n');
return 0;
}
/*
for(int x:nums)即
for(int i=0;i<=nums.length;i++)
*/
前向星
优点:
a.内存利用率高:相比vector实现的邻接表而言,可以准确开辟最多边数的内存,不像vector实现的邻接表有爆内存的风险
b.对不确定的边操作比较方便,和邻接表一样不会遍历到不存在的边
缺点:
a.操作复杂一点:要求比较熟练,不熟练写起来比较慢
b.重边不好处理:这点与邻接表一样,只有通过遍历判重
c.对确定边操作效率不高:也与邻接表一样,不能通过两点马上确定边,只能遍历查找
拓扑排序:
#include<bits/stdc++.h>
#define maxn 5010
#define maxe 500010
using namespace std;
const int mod=80112002;
int n,m,h[maxn],in[maxn],out[maxn],f[maxn],ans;
struct AB{
int a,b,n;
}d[maxe];
queue<int> q;
int main(){
cin>>n>>m;
for(int i=1,a,b;i<=m;i++){
scanf("%d%d", &a, &b);
d[i].a=a, d[i].b=b;
d[i].n=h[a], h[a]=i;//注意
out[a]++, in[b]++;
}
for(int i=1;i<=n;i++){
if(in[i]==0){
f[i]=1;//注意
q.push(i);
}
}
while(!q.empty()){
int a=q.front(); q.pop();
for(int k=h[a]; k ;k=d[k].n){
int b=d[k].b;
f[b]+=f[a];
f[b]%=mod;
in[b]--;
if(in[b]==0){
if(out[b]==0){
ans+=f[b];
ans%=mod;
}//出度为0的点为食物链终点,记录答案,并且不必入队
else q.push(b);//没有出度,那么进队了也没有意义
}
}
}
cout<<ans;
}
推荐好文:存图的三种方式