算法-图论

图论

强联通分量

1. 2021-4-6 tarjan算法

题目:

在一次聚会中,教授们被要求写下自己认可哪位教授的学术成果(也可以写自己,且可能出现重复)。已知,如果教授 A 认可教授 B ,且教授 B 认可教授 C,那么即可视为教授 A 也认可教授 C。现在我们想知道有多少对教授是两两互相认可的?

输入描述:

第一行两个正整数,教授人数 n,以及认可关系总数 m ;
接下来 m 行,每行两个正整数 x 和 y,表示教授 x 认可教授 y(x , y可能相等且可能出现重复)

输出描述:

一行一个数字表示答案,即互相认可的教授有多少对。	

示例1
输入

5 6
1 3
2 1
3 2
3 5
4 5
5 4

输出

4

说明

4对互相认可的教授分别是1和2、1和3、2和3、4和5。

思路

一开始看到以为是并查集,但这道不只是A->C,还需要区分C->A,那么问题就转化成了求每个强连通分量了。需要用到tarjan算法。

注意每次求出强连通分量个数为n时,对数应该为n*(n-1)/2个。

tarjan算法模板
tarjan算法过程

代码:

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,vector<int>> edges;
vector<int> dfn(50001,0);
vector<int> low(50001,0);
vector<bool> instack(50001,false);
stack<int> st;
int dfn_num=0;
int ans=0;
void tarjan(int now){
   
    dfn[now]=low[now]=dfn_num++;
    instack[now]=true;
    st.push(now);
    for(auto next:edges[now]){
   
        if(!dfn[next]){
   
            tarjan(next);
            low[now]=min(low[now],low[next]);
        }
        else if(instack[next]){
   
            low[now]=min(low[now],dfn[next]);
        }
    }
    if(dfn[now]==low[now]){
   
        int cnt=0;
        int top_elem;
        do{
   
            top_elem=st.top();
            st.pop();
            cnt++;
            instack[top_elem]=false;
        }while(top_elem!=now);
        if(cnt>1)ans+=(cnt*(cnt-1)/2);
    }
}
int main(){
   
    int m,n;
    scanf("%d%d",&n,&m);
    while(m>0){
   
        int x,y;
        scanf("%d%d",&x,&y);
        edges[x].push_back(y);
        m--;
    }
    for(int i=1;i<=n;++i){
   
        if(!dfn[i])tarjan(i);
    }
    cout<<ans;
    return 0;
}

最短路径

dijsktra算法

1. 2021-4-1 dijsktra最短路径最大值

题目:

网易严选建有N个自营仓分布在全国各地,标记为仓库1到N。
给定一个配货时间组(v,u,w),v为出发仓库,u为目标仓库,w为从出发仓库到目标仓库的耗时时间。可能存在仓库间过远,无法支持调拨转货。
指定一个出发仓库K,我们需要将供应商发送到K仓库的货配送到各个仓库。问配送到所有可到达仓库所要最短时间?如果无法全部调拨到,

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值