文章目录
- 前言
- [P5318 【深基18.例3】查找文献](https://www.luogu.com.cn/problem/P5318)(图的两种遍历方式)
- [P3916 图的遍历](https://www.luogu.com.cn/problem/P3916)(反向建边,dfs)
- [P1113 杂务](https://www.luogu.com.cn/problem/P1113)(拓扑排序)
- [P4017 最大食物链计数](https://www.luogu.com.cn/problem/P4017)(拓扑排序,递推)
- [P1807 最长路](https://www.luogu.com.cn/problem/P1807)(bfs)
前言
P5318 【深基18.例3】查找文献(图的两种遍历方式)
这道题同时考察了图的深度优先遍历和宽度优先遍历,很不错!
邻接表习惯用y总的静态链表,当然用vector
也不错
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef pair<int,int> PII;
#define x first
#define y second
const int N = 100010, M = 1000010;
int n,m;
int h[N],e[M],ne[M],idx; // y总的做法,头插,顺序不对,如果不考虑顺序可用
bool st[N];
vector<int> Adj[N]; // 用vector实现邻接表,换种实现方式
vector<PII> nums;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u)
{
st[u]=true;
printf("%d ",u);
for(int i=0;i<Adj[u].size();i++)
{
int j=Adj[u][i];
if(!st[j]) dfs(j);
}
}
void bfs(int u) // bfs需借助queue来实现,dfs是系统栈自动实现
{
memset(st,0,sizeof st); // dfs用过了,清空一下状态
queue<int> q;
q.push(u);
st[u]=true;
// 宽搜框架
while(q.size())
{
int t=q.front();
q.pop();
printf("%d ",t);
for(int i=0;i<Adj[t].size();i++)
{
int j = Adj[t][i];
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
nums.push_back({a,b});
}
sort(nums.begin(), nums.end()); // 考虑顺序,先排一下序
for(int i=0;i<nums.size();i++)
{
int a=nums[i].x,b=nums[i].y;
//add(a,b); // y总这种是头插法,插入的顺序不对,导致搜索排序不对
Adj[a].push_back(b); // 改邻接表存一下,换种实现方式
//printf("%d %d\n",a,b);
}
dfs(1);
printf("\n");
bfs(1);
return 0;
}
P3916 图的遍历(反向建边,dfs)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int n,m;
const int N = 100010;
vector<int> Adj[N];
int cnt[N]; // 判重可用cnt代替
//bool st[N]; // 判重数组不可少,只搜索一遍
void dfs(int u,int d) // d : 带的最大编号
{
if(cnt[u]) return; // 先前遍历过,直接返回
cnt[u]=d;
for(int i=0;i<Adj[u].size();i++)
{
int j=Adj[u][i];
dfs(j,d);
}
}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
Adj[b].push_back(a); // 反向建边 + DFS
}
//dfs(1); // 又忘记了调用函数~~
for(int i=n;i>=1;i--) dfs(i,i);
for(int i=1;i<=n;i++)
{
printf("%d ",cnt[i]);
}
return 0;
}
P1113 杂务(拓扑排序)
拓扑排序,递推
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int N = 10010;
int n;
vector<int> adj[N];
int w[N];
int d[N];
int dist[N];
void bfs()
{
memset(dist,-1,sizeof dist);
queue<int> q;
for(int i=1;i<=n;i++)
if(d[i] == 0)
{
q.push(i);
dist[i]=w[i];
}
while(q.size())
{
auto t = q.front();
q.pop();
for(auto c : adj[t])
{
dist[c] = max(dist[c],dist[t] + w[c]);
d[c] --;
if(d[c] == 0) q.push(c);
}
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++)
{
int a,b;
cin >> a >> b; // 居然忘记输入了
w[a] = b;
int x;
while(cin >> x, x)
{
d[a] ++;
adj[x].push_back(a);
}
}
bfs();
int res=0;
for(int i=1;i<=n;i++) res=max(res,dist[i]);
cout<<res;
//for(int i=1;i<=n;i++) cout<<dist[i]<<endl;
return 0;
}
P4017 最大食物链计数(拓扑排序,递推)
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N = 500010, mod = 80112002;
int n,m;
int h[N],e[N],ne[N],idx;
int d[N],out[N]; // 记录每个点的入度,出度
int f[N]; // 到这个点的食物链条数
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a] ,h[a] = idx ++ ;
}
void topsort()
{
queue<int> q;
// 寻找入度为0的点,生产者
for(int i=1;i<=n;i++)
if(d[i] == 0)
{
q.push(i);
f[i] = 1;
}
while(q.size())
{
int t = q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]) // 遍历所有出边
{
int j = e[i];
d[j] --;
f[j] = (f[t] + f[j]) % mod; // 状态转移
if(d[j] == 0) q.push(j);
}
}
}
int main()
{
memset(h,-1,sizeof h); // 记得初始化头结点
scanf("%d%d",&n,&m);
int a,b;
while(m--)
{
scanf("%d%d",&a,&b);
add(a,b);
d[b] ++ ;
out[a] ++ ;
}
topsort(); // 忘记调用了~~
int res=0;
for(int i=1;i<=n;i++)
if(out[i] == 0) res = (res + f[i]) % mod; // 出度为0的点为消费者
printf("%d\n",res);
return 0;
}
P1807 最长路(bfs)
只有被更新的点,才入队去更新其他点
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int N = 1510, M = 50010;
struct Node{
int a,b;
};
int n,m;
int dist[N];
int g[N][N];
void bfs()
{
queue<int> q;
memset(dist,-1,sizeof dist);
dist[1] = 0;
q.push(1);
while(q.size())
{
int t=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
if(g[t][i] && dist[i] < dist[t] + g[t][i])
{
dist[i] = dist[t] + g[t][i];
q.push(i);
}
}
}
}
int main()
{
cin >> n >> m;
for(int i=0;i<m;i++)
{
int a,b,c;
cin >> a>> b >> c;
g[a][b] = max(g[a][b],c);
}
bfs();
cout<<dist[n];
return 0;
}