acwing算法基础课学习记录1(2024.3.28)

昨天学习了图的深搜广搜,拓扑排序,先自己写了一遍昨天学习的代码

树的重心

#include<cstring>
#include<iostream>
using namespace std;
const int N=100010;
int h[N],idx,e[N*2],ne[N*2],n,st[N];
int ans=N;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int x){
    int nu=0,bu=0;
    for(int i=h[x];i!=-1;i=ne[i]){
        if(!st[e[i]]){
            st[e[i]]=1;
            int su=dfs(e[i]);
            nu+=su;
            bu=max(bu,su);
        }
    }
    bu=max(bu,n-nu-1);
    ans=min(ans,bu);
    return nu+1;
}
int main(){
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++){
        int a,b;
        cin>>a>>b;
        add(a,b),add(b,a);
    }
    dfs(1);
    cout<<ans;
    return 0;
}

图中点的层次

#include<iostream>
#include<queue>

#include<cstring>
using namespace std;
const int N=100010;
int h[N],e[N],ne[N],idx,n,m,d[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int x){
    queue<int>q;
    memset(d,-1,sizeof d);
    d[x]=0;
    q.push(x);
    while(q.size()){
        int t=q.front();
        // cout<<t<<' ';
        q.pop();
        for(int i=h[t];i!=-1;i=ne[i]){
            int tt=e[i];
            if(d[tt]==-1){
                q.push(tt);
                // cout<<t<<' '<<d[t]<<' ';
                // cout<<tt<<' ';
                d[tt]=d[t]+1;
                if(tt==n)return ;
            }
        }
    }
}
int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
    }
    bfs(1);
    cout<<d[n];
}

有向图的拓扑序列

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N=100010;
int ru[N],cu[N],h[N],idx,e[N],ne[N],st[N];
int n,m;
void add(int x,int y){
    e[idx]=y;
    ne[idx]=h[x],h[x]=idx++;
    ru[y]++,cu[x]++;

}
vector<int>cc;
void tp(){
    queue<int>q;
    int ip=1;
    for(int i=1;i<=n;i++){
        if(!ru[i]){
            q.push(i);
            cc.push_back(i);
        }
    }
    while(q.size()){
        int t=q.front();
        q.pop();
        for(int i=h[t];i!=-1;i=ne[i]){
            int tt=e[i];
            ru[tt]--;
            if(!ru[tt]){
                q.push(tt);
                cc.push_back(tt);
            }
        }
    }
    // cout<<q.size();
    if(cc.size()==n){
        for(auto it:cc){
            cout<<it<<' ';
        }
    }else cout<<-1;

}
int main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        add(x,y);
    }
    tp();

}

随后直播课搜索与图论(3)看了一半

知识点总结:

        

        最短路问题     n表示图点的个数,m表示边数
      1.单元最短路
        (1)边权都为正数
            方案:a.朴素dijkstra算法 时间复杂度O(n^2)  适用于稠密图(邻接矩阵来存):m与n^2一个级别
                b.堆优化的Dijkstra算法 时间复杂度O(mlogn)  稀疏图(邻接表来存):(m与n一个级别)
        (2)存在负权边
            方案:a.BellmanFord算法 时间复杂度O(n*m)
                b.SPFA   一般平均时间复杂度O(m)最坏O(n*m)
                    但是对于经过不超过k条边问题只能用BellmanForyd
      2.多源汇最短路  Floyd  时间复杂度O(n^3)

随后自己写了两个模板题

 Dijkstra求最短路 I

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100010;

int lin[510][510];
int dist[510],st[510];

int n,m;
int dijk(int x){
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i=1;i<n;i++){
        int t=-1;
        for(int j=1;j<=n;j++){
            if(!st[j]&&(t==-1||dist[j]<dist[t])){
                t=j;
            }
        }
        st[t]=1;
        for(int k=1;k<=n;k++){
            if(dist[k]>dist[t]+lin[t][k]){
                dist[k]=dist[t]+lin[t][k];
            }
        }
    }
    if(dist[x]==0x3f3f3f3f)return -1;
    else return dist[x];
}
int main(){
    memset(lin,0x3f,sizeof lin);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        if(z<lin[x][y])lin[x][y]=z;
    }
    cout<<dijk(n);
    return 0;
}

Dijkstra求最短路 II

//出现的问题:第一次用priority_queue 定义不熟悉  后面两个参数应该与第一个参数保持一致
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=150010;

int dist[N];
int h[N],e[N],ne[N],idx,w[N];
int st[N];
int n,m;
void add(int x,int y,int z){
    ne[idx]=h[x],e[idx]=y,w[idx]=z,h[x]=idx++;
}
int dijks(int x){
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >p;
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    p.push({0,1});
    while(p.size()){
        auto t=p.top();
        p.pop();
        int der=t.second,di=t.first;
         if(st[der])continue;//不写会TLE
        st[der]=1;

        for(int i=h[der];i!=-1;i=ne[i]){
            int xx=e[i],yy=w[i];
            dist[xx]=min(dist[xx],dist[der]+w[i]);
            p.push({dist[xx],xx});
        }
    }
    if(dist[x]==0x3f3f3f3f)return -1;
    else return dist[x];
}
int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        add(x,y,z);
    }
    cout<<dijks(n);
    return 0;
}

明日任务:把直播课搜索与图论(2)看完 然后自己写一遍明天要学的模板  放松的时候多抄抄今天的模板dijkstra与明天将要学的模板      奢望:以上能够比较快的完成,然后学习3的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值