【数据结构1-4】图的基本应用

前言

在这里插入图片描述

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值