Week9-图

Week9-图

第一题(查找文献)

评析:存图后bfs加dfs就可以了,注意排序,这题不难

#include<bits/stdc++.h>

using namespace std;

int a[100007];

vector<vector<int> >vv;

int m,n;

void dfs(int x)

{

       if(a[x]==1)  return ;

       cout<<x<<" ";

       a[x]=1;

       for(int i=0;i<vv[x].size();i++)

       dfs(vv[x][i]);

}

void bfs()

{

       queue<int> q;

       memset(a,0,sizeof(a));

       q.push(1);

       a[1]=1;

       while(!q.empty())

       {

              int f=q.front();

              q.pop();

              cout<<f<<" ";

              for(int i=0;i<vv[f].size();i++)

              {

                     if(a[vv[f][i]]==1) continue;

                     q.push(vv[f][i]);

                     a[vv[f][i]]=1;

              }

       }

}

int main()

{

       memset(a,0,sizeof(a));

       cin>>m>>n;

       vector<int>w;

       for(int i=0;i<=n;i++)

       {

              vv.push_back(w);

       }

       for(int i=0;i<n;i++)

       {

              int u,v;

              cin>>u>>v;

              vv[u].push_back(v);

       }

       for(int i=0;i<=n;i++)

              sort(vv[i].begin(),vv[i].end());

       dfs(1);

       cout<<endl;

       bfs();

}

第二题(floyd)

评析:模板题,背一下祝佬的模板三个循环再加上a[i][j]=min(a[i][j],a[i][k]+a[k][j]);

#include<bits/stdc++.h>

using namespace std;

const int mod=998244354;

int n,m;

int f[505][505];

int a[505][505];

int main(){

    cin>>n>>m;

    memset(a,0x3f,sizeof(a));//记得先初始化为无穷大

    for (int i=1; i<=n; i++)  a[i][i]=0;

    for (int i=1; i<=m; i++)

       {

        int u,v,w;

        cin>>u>>v>>w;

        a[u][v]=min(w,a[u][v]);

        a[v][u]=min(w,a[v][u]);

    }//邻接表存图

    for (int k=1; k<=n; k++)

        for (int i=1; i<=n; i++)

            for (int j=1; j<=n; j++)

                a[i][j]=min(a[i][j],a[i][k]+a[k][j]);//floyd算法

    int sum=0;

    for (int i=1; i<=n; i++)

       {

        for (int j=1; j<=n; j++)

              {

            sum=(sum+a[i][j])%mod;//取模

        }

        cout<<sum<<endl;

        sum=0;

    }

    return 0;  

}

第三题(dijkstra)

评析:视频里讲了,要注意链式前向星和优先队列和堆优化,可以大大简化时间

#include<bits/stdc++.h>

using namespace std;

struct edge

{

    int to, dis, next;

};

edge e[500005];

int head[100005], dis[100005], cnt;

bool vis[100005];

int n, m, s;

inline void add_edge(int u, int v, int d)

{

    cnt++;

    e[cnt].dis = d;

    e[cnt].to = v;

    e[cnt].next = head[u];

    head[u] = cnt;

}//链式前向星存图

struct node

{

    int dis;

    int pos;

    bool operator <(const node &x)const

    {

        return x.dis < dis;

    }

};

std::priority_queue<node> q;

inline void dijkstra()

{

    dis[s] = 0;

    q.push(node{0, s});

    while(!q.empty())

    {

        node tmp = q.top();

        q.pop();

        int x = tmp.pos, d = tmp.dis;

        if(vis[x]) continue;

        vis[x] = 1;

        for( int i = head[x]; i; i = e[i].next)

        {

            int y = e[i].to;

            if( dis[y] > dis[x] + e[i].dis )

            {

                dis[y] = dis[x] + e[i].dis;

                if(!vis[y])  q.push( node{dis[y], y});

            }

        }

    }

}//不断刷新最短路径

int main()

{

    cin>>n>>m>>s;

    for(int i = 1; i <= n; i++) dis[i] = 0x7fffffff;

    for(int i = 0; i < m; i++)

    {

        int u, v, d;

        cin>>u>>v>>d;

        add_edge(u,v,d);

    }

    dijkstra();

    for( int i = 1; i <= n; i++)

        cout<<dis[i]<<" ";

    return 0;

}

堆优化模板(借鉴了大佬的):

struct edge {

  int v, w;

};

struct node {

  int dis, u;

  bool operator>(const node& a) const { return dis > a.dis; }

};

vector<edge> e[N];//邻接表存带权边

int dis[N], vis[N];//dis表示与起点距离,vis表示是否收录最短路径

priority_queue<node, vector<node>, greater<node> > q;//小顶堆,按照与起点距离排序

void dijkstra(int n, int s) {

    memset(dis, 0x3f, sizeof(dis));

    dis[s] = 0;

    q.push({0, s});

    while (!q.empty()) {

        int u = q.top().u;

        q.pop();

        if (vis[u]) continue;

        vis[u] = 1;

        for (auto ed : e[u]) {

        int v = ed.v, w = ed.w;

        if (dis[v] > dis[u] + w) {

            dis[v] = dis[u] + w;

            q.push({dis[v], v});

        }

        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值