week9(图论1)

图论1

9-1 查找文献

题目链接

P5318

解题思路

邻接表存图,排序后使用dfsbfs即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=1e6+5;
int n,m;
bool vis[maxn];
vector <int> a[maxn];
queue <int> q;
void dfs(int k){
    cout<<k<<" ";
    int l=a[k].size();
    for (int i=0; i<l; i++){
        int to=a[k][i];
        if (!vis[to]){
            vis[to]=1;
            dfs(to);
        }
    }
}

void bfs(int k){
    q.push(k);
    
    while (!q.empty()){
        int to=q.front();
        q.pop();
        cout<<to<<" ";
        int l=a[to].size();
        for (int i=0; i<l; i++){
            int next=a[to][i];
            if (!vis[next]){
                vis[next]=1;
                q.push(next);
            }
        }
    }

}

int main(){
    cin>>n>>m;
    for (int i=1; i<=m; i++){
        int u,v;
        scanf("%d%d",&u,&v);
        a[u].push_back(v);
    }
    for (int i=1; i<=n; i++){
        sort(a[i].begin(),a[i].end());
    }
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    dfs(1);
    cout<<endl;
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    bfs(1);    

    return 0;   
}

笔者前几天才想明白,dfsbfs使用时必然是联通图的情况,所以只需要dfs(1)bfs(1)就能走遍整个图,不需要再外加一个for(i:1~n)

9-2 floyd

题目链接

U80592

解题思路

先明白floyd的原理
在这里插入图片描述
本质上是三重循环去找,但是因为递推式右边中都为k-1,所以空间上可以降为二维。
floyd是一种动态规划,复杂度比较高,时间复杂度O(N3),是求每对结点之间的最短路,适用于任何图:有向无向、边权正负,但是最短路必须存在。(不能有个负环)
注意: 本题需要取模运算,但只能在最后累加时候取模。在floyd运算时,即a[i][j]=min(a[i][j],a[i][k]+a[k][j]);语句中不可取模,否则取模后两个数的大小关系可能会发生改变。

#include<bits/stdc++.h>
using namespace std;

const int maxn=5e2+5;
typedef long long ll;
const ll MOD=998244354;
int n,m;
ll f[maxn][maxn];
ll a[maxn][maxn];

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++){
        ll 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]);
            }
        }
    }
    ll 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;   
}

9-3 单源最短路径

题目链接

P4779

解题思路

Dijkstra是一种贪心思想,是求单源最短路,适用于非负权图,不能检测负环。
在链式前向星使用和优先队列优化下,时间复杂度O(M logM)。


#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=2e5+5;
const int inf=0x3f3f3f3f;
int n,m,s;
int f[maxn];
struct node{
    int to,w,next;
};
int first[maxn];
node e[maxm];
struct edge{
    int w,p;
    bool operator <(const edge x) const {
        return x.w<w;
    }
};
priority_queue <edge> q;
bool vis[maxn];
int main(){
    cin>>n>>m>>s;
    for (int i=1; i<=m; i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        e[i].to=v;
        e[i].w=w;
        e[i].next=first[u];
        first[u]=i;
    }
    memset(f,0x3f,sizeof(f));
    
    memset(vis,0,sizeof(vis));
    f[s]=0;
    q.push({0,s});

    while (!q.empty()){
        int p=q.top().p;
        q.pop();

        if (vis[p]){
            continue;
        }
        vis[p]=1;
        for (int i=first[p]; i; i=e[i].next){
            int to=e[i].to;
            int dis=e[i].w;
            if (f[to]>f[p]+dis){
                f[to]=f[p]+dis;
                q.push({f[to],to});
            }
        }
    }

    for (int i=1; i<=n; i++){
        cout<<f[i]<<" ";
    }
    return 0;   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值