牛客算法竞赛入门笔记4

别问为什么没发树型dp和状压dp,因为我不是负责这块的,所以就做了一些例题略微了解了一下,没有发的必要,下面的图论是我负责的,先放一点比较经典的题目,也是雨巨拉的例题,后面应该会按题型发更多的图论(等这个入门班的笔记完结后)。

公交线路 (nowcoder.com)

板子题:链式前向星+堆优化dij(复杂度:O((n+m)logm )

链式前向星详解:深度理解链式前向星ACdreamer-CSDN博客链式前向星(其实就是静态链表)

 #include <bits/stdc++.h>
 using namespace std;
 #define fi first
 #define se second
 #define int long long
 #define ll long long
 #define pint pair<int,int>
 #define mod 998244353
 #define INF 0x3f3f3f3f
 struct node{
     int to,val,ne;
 };
 node mp[20010];
 int head[1010];
 int dis[1010];
 int visit[1010];
 int pos=0;
 int n,m,s,en;
 void addedge(int a,int b,int val){
     mp[pos].ne=head[a];
     head[a]=pos;
     mp[pos].to=b;
     mp[pos].val=val;
     pos++;
 }
 void dij(int s,int en){
     priority_queue<pint>q;
     dis[s]=0;
     q.push(make_pair(0,s));
     while(!q.empty()){
         pint t=q.top();
         q.pop();
         if(visit[t.se]==1){
             continue;
         }       
         visit[t.se]=1;
         for(int i=head[t.se];i!=-1;i=mp[i].ne){
             if(mp[i].val+dis[t.se]<dis[mp[i].to]){
                 dis[mp[i].to]=mp[i].val+dis[t.se];
                 //优先队列默认从大到小,改成负数就不用重写比较函数了
                 q.push(make_pair(-dis[mp[i].to],mp[i].to));
             }
         }   
     }
 }
 signed main(){
     memset(head,-1,sizeof(head));
     memset(visit,0,sizeof(visit));
     cin>>n>>m>>s>>en;
     for(int i=0;i<=n;i++){
         dis[i]=INF;
     }
     for(int i=0;i<m;i++){
         int a,b,c;
         cin>>a>>b>>c;
         addedge(a,b,c);
         addedge(b,a,c);
     }
     dij(s,en);
     if(dis[en]==INF){
         cout<<-1<<endl;
         return 0;
     }
     cout<<dis[en]<<endl;
     return 0;
 }

挖沟 (nowcoder.com)

板子题,最小生成树(堆优化prim+链式前向星)

 #include <bits/stdc++.h>
 using namespace std;
 struct node{
     int to,ne,val;
 };
 node edge[1000010];
 int head[100010];
 int cnt=0;
 void addedge(int a,int b,int val){
     edge[++cnt].ne=head[a];
     edge[cnt].val=val;
     edge[cnt].to=b;
     head[a]=cnt;
 }
 struct node2{
     int a,val;
     bool operator < (const node2 &a)const{
         return this -> val > a.val;
     }
 };
 priority_queue<node2>q;
 int dis[100010];
 int visit[100010];
 void prim(){
     node2 tem;
     tem.a=1;
     tem.val=0;
     dis[1]=0;
     q.push(tem);
     while(!q.empty()){
         tem=q.top();
         q.pop(); 
         cout<<tem.a<<endl;
         if(visit[tem.a]==1){
             continue;
         }
         visit[tem.a]=1;
         for(int i=head[tem.a];i!=-1;i=edge[i].ne){
             if(visit[edge[i].to]==1){
                 continue;
             }
             if(edge[i].val<dis[edge[i].to]){
                 dis[edge[i].to]=edge[i].val;
                 tem.a=edge[i].to;
                 tem.val=dis[edge[i].to];
                 q.push(tem);
             }
         }
     }
 }
 int main(){
     int n,m;
     cin>>n>>m;
     memset(head,-1,sizeof(head));
     memset(dis,0x3f,sizeof(dis));
     for(int i=0;i<m;i++){
         int a,b,c;
         cin>>a>>b>>c;
         addedge(a,b,c);
         addedge(b,a,c);
     }
     prim();
     int ans=0;
     for(int i=1;i<=n;i++){
         ans+=dis[i];
     }
     cout<<ans<<endl;
     return 0;
 } 

[HNOI2015]菜肴制作 (nowcoder.com)

经典问题了属于是,我们如果按照题目要求去想的话会发现很难写(因为不是字典序最小问题),所以我们采用经典反向建图,问题就转化成逆字典序最大,算是图论的一种经典策略,涉及到顺序问题的正着不好想就试一下反向建图。然后就求出这个图的字典序最大的拓扑排序然后反向输出就行了。

又有个地方要注意:链式前向星记录时,多组数据除了要初始化head和du以外,还要把cnt(代表当前存到第几个位置)也初始化才行,这里wa了好几发,呜呜呜。

 #include <bits/stdc++.h>
 using namespace std;
 #define fast ios::sync_with_stdio(0), cin.tie(0)
 struct node{
     int to,ne;
 };
 node edge[100001];
 int du[100001];
 int head[100001];
 int cnt=0;
 void addedge(int a,int b){
     edge[cnt].ne=head[a];
     edge[cnt].to=b;
     head[a]=cnt;
     cnt++;
 }
 priority_queue<int>q;
 vector<int>ans;
 int main(){
     fast;
     int t;
     cin>>t;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wuhudaduizhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值