程序猴算法日记

二、堆

知识点

在这里插入图片描述
后俩个stl实现不了

在这里插入图片描述
每个点比自己儿子小
在这里插入图片描述
一维数组存储堆
堆的两个操作
up和down,可以组成其他的操作
在这里插入图片描述
删除最小值数组删头难删尾容易,所以把第一个点和最后一个点交换再删
变大往下沉,变小往上走
在这里插入图片描述

down和up只会执行一个
下标从1开始,因为0的左儿子还是0,冲突了
在这里插入图片描述
原理是最后一层降不了,倒数第二层只能降一层,倒二降两层
时间复杂度从nlogn降到n
因为是从下往上,所以能保证两个儿子都是堆了
在这里插入图片描述
第几次插入的点和堆中点的关系、堆中点是第几次插入的点的关系
hp[i]=j就是堆中下标为i的点是第j个插入的数,因为现在给的是堆中元素的下标,所以要先知道它是第几个插入的点才好改映射关系啊
一般的堆down和up都够用了,但是dijiakstra里面堆可能会用到
删除和修改堆中数才存映射关系啊

1.堆排序

在这里插入图片描述

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

int h[N],idx,size1;

int down(int x){
    int t=x;
    if(x*2<=size1&&h[x*2]<h[t]) t=x*2;
    if(x*2+1<=size1&&h[x*2+1]<h[t]) t=x*2+1;
    if(t!=x){
        swap(h[x],h[t]);
        down(t);
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    size1=n;
    for(int i=1;i<=n;i++) cin>>h[i];
    for(int i=n/2;i;i--) down(i);
    while(m--){
        int t=h[1];
        cout<<t<<' ';
        h[1]=h[size1];
        size1--;
        down(1);
    }
}

2.模拟堆

在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
#include<algorithm>

const int N=100010;

int h[N],idx,size1;
int ph[N],hp[N];

void swap_heap(int x,int y){
    swap(ph[hp[x]],ph[hp[y]]);//先改最外层的映射啊,不然待会内层改了,外层改个der,外层依赖内层
    swap(hp[x],hp[y]);
    swap(h[x],h[y]);
}

int down(int x){
    int t=x;
    if(x*2<=size1&&h[t]>h[x*2]) t=x*2;
    if(x*2+1<=size1&&h[t]>h[x*2+1]) t=x*2+1;
    if(t!=x){
        swap_heap(x,t);
        down(t);
    }
}

int up(int x){
    while(x/2&&h[x/2]>h[x]){
        swap_heap(x/2,x);
        x/=2;
    }
    // if(x/2&&h[x/2]>h[x]){
    //     swap_heap(x/2,x);
    //     up(x/2);
    // }
}

int main(){
    int n;
    int m=0;
    cin>>n;
    while(n--){
        string ops;
        cin>>ops;
        if(ops=="I"){
            int x;
            cin>>x;
            m++;
            h[++size1]=x;
            hp[size1]=m;
            ph[m]=size1;
            up(size1);//从下到上建堆啊,为啥呢,可以归纳证明一下的噢
        }
        if(ops=="PM"){
            cout<<h[1]<<endl ;
        }
        if(ops=="DM"){
            swap_heap(1,size1);
            size1--;
            down(1);
        }
        if(ops=="D"){
            int t;
            cin>>t;
            int y=ph[t];//存下位置待会过来调
            swap_heap(ph[t],size1);//会改变原本那个元素的映射关系的
            size1--;
            up(y);//调删掉元素之前的那个位置的新元素啊
            down(y);
        }
        if(ops=="C"){
            int t,c;
            cin>>t>>c;
            h[ph[t]]=c;
            up(ph[t]);
            down(ph[t]);
        }
    }
}

3.数组中第k个最大元素

在这里插入图片描述

class Solution {
public:

    static const int N=10010;

    int size1;

    int h[N];

    void down(int x){
        int t=x;
        if(x*2<=size1&&h[t]<h[x*2]) t=x*2;
        if(x*2+1<=size1&&h[t]<h[x*2+1]) t=x*2+1;
        if(x!=t){
            swap(h[x],h[t]);
            down(t);
        }
    }

    void up(int x){
        if(x/2&&h[x/2]<h[x]){
            swap(h[x/2],h[x]);
            up(x/2);
        }
    }

    int findKthLargest(vector<int>& nums, int k) {
        size1=0;
        for(int i=1;i<=nums.size();i++){
            h[i]=nums[i-1];
            up(i);
            size1++;
        }
        while(k--){
            if(!k) return h[1];
            swap(h[1],h[size1]);
            size1--;
            down(1);
        }
        return 0;
    }
};

4.超级丑数

在这里插入图片描述

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int> &primes)
    {
        priority_queue<long long, vector<long long>, greater<long long>> buff;
        unordered_set<long long> primeset;

        buff.push(1);
        primeset.insert(1);
        long long i = 1;
        int count = 0;
        while (count < n) {
            count++;
            i = buff.top();
            buff.pop();
            for (long long prime : primes) {
                long long next = i * prime;
                if (next<=INT32_MAX && !primeset.count(next)) {
                    buff.push(next);
                    primeset.insert(next);
                }
            }
        }

        return i;
    }
};

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        priority_queue<int,vector<int>,greater<int>>heap;
        int N=primes.size();
        heap.push(1);
        int res;
        while(n>0){
            long m=heap.top();
            heap.pop();
            if(m==res) continue;
            res=m;
            if(!n){
                return m;
            }
            for(auto i:primes){
                if(i<=INT_MAX/m){
                    heap.push(i*m);
                }else{
                    break;
                }
                if(res%i==0)    break; // 欧拉筛
            }
            n--;
        }
        return res;
    }
};

5.设计推特

在这里插入图片描述
在这里插入图片描述

typedef pair<int, int> PII;

class Twitter {
private:
    unordered_map<int, unordered_set<int>> followers_;  // id - followers
    unordered_map<int, vector<PII>> contents_;  // id - {time, twitterId}
    int time = 0;
    
public:
    Twitter() {
        followers_.clear();
        contents_.clear();
        time = 0;
    }
    
    void postTweet(int userId, int tweetId) {
        contents_[userId].push_back({time++, tweetId});
    }
    
    vector<int> getNewsFeed(int userId) {  // userId不存在则返回空数组
        priority_queue<PII, vector<PII>, greater<PII>> q;
        
        for (PII item : contents_[userId]) {   // 先考虑自己
            q.push(item);
            if (q.size() > 10) q.pop();
        }
        
        for (int followeeId : followers_[userId]) {   // 再考虑他人 
            for (PII item : contents_[followeeId]) {
                q.push(item);
                if (q.size() > 10) q.pop();
            }
        }
        vector<int> ret;
        while (!q.empty()) {
            ret.push_back(q.top().second);
            q.pop();
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }

    void follow(int followerId, int followeeId) {
        if (followerId == followeeId) return;
        followers_[followerId].insert(followeeId);
    }
    
    void unfollow(int followerId, int followeeId) {
        if (!followers_[followerId].count(followeeId)) return;
        followers_[followerId].erase(followeeId);
    }
};

6.前K个高频元素

在这里插入图片描述

class Solution {
public:

    typedef pair<int,int> PII;

    const static int L=100010;

    map<int,int> hash;

    int c[L];

    vector<PII> h;

    vector<int> topKFrequent(vector<int>& nums, int k) {
        priority_queue<PII,vector<PII>,less<PII>>heap;
        int N=nums.size();
        for(int i=0;i<N;i++) {
            hash[nums[i]]++;
        }
        for(auto i:hash) {
            cout<<i.first<<' '<<i.second<<endl;
            heap.push({i.second,i.first});
        }
        vector<int> res;
        while(k--){
            res.push_back(heap.top().second);
            heap.pop();
        }
        return res;
    }
};

7.查找和最小的K对数字

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    typedef pair<int,pair<int,int>> PIP;
    vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        priority_queue<PIP,vector<PIP>,less<PIP>>heap;//大根堆删掉最大值留最小值嘛
        int cnt=0;
        for(int i=0;i<nums1.size()&&i<k;i++){
            for(int j=0;j<nums2.size()&&j<k;j++){//第一个条件是避免遍历多了,第二个是不能越界
                if(heap.size()<k||heap.top().first>nums1[i]+nums2[j])
                {
                    if(heap.size()==k) heap.pop();
                    heap.push({nums1[i]+nums2[j],{nums1[i],nums2[j]}});
                }
            }
        }
        vector<vector<int>>res;
        for(int i=0;i<k;i++){
            if(cnt==nums1.size()*nums2.size()) break;
            vector<int> temp;
            pair<int,int> tp=heap.top().second;
            heap.pop();
            temp.push_back(tp.first);
            temp.push_back(tp.second);
            res.push_back(temp);
            cnt++;
        }
        reverse(res.begin(),res.end());//大根堆反过来啊
        return res;
    }
};

8.分割数组为连续子序列

在这里插入图片描述
在这里插入图片描述

class Solution {
public:

    typedef pair<int,int> PII;//头代表末尾的元素,尾表示子序列的长度

    bool isPossible(vector<int>& nums) {
        priority_queue<PII,vector<PII>,greater<PII>>heap;//小根,长度短最急,优先匹配
        int N=nums.size();
        for(int i=0;i<N;i++){
            if(heap.empty()){
                heap.push({nums[i],1});
            }
            else{
                while(!heap.empty()){
                    auto j=heap.top();
                    if(nums[i]-1>j.first){//当前最小的这个都满足不了只能抛出了
                        if(j.second<3)  return false;//抛出的有问题
                        else heap.pop();//抛出没问题,继续匹配下一个
                    }else{
                        break;//符合加进堆的条件,待会看看怎么加
                    }
                }
                auto j=heap.top();
                if(nums[i]-1==j.first){//加之前的最急的这个组
                    int j1=++j.first;
                    int j2=++j.second;
                    heap.pop();
                    heap.push({j1,j2});
                }else{
                    heap.push({nums[i],1});//新开一个组
                }
            }
        }
        while(!heap.empty()){
            auto i=heap.top();
            if(i.second<3) return false;
            heap.pop();
        }
        return true;
    }
};

9.网络延迟时间

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    static const int N=110;

    vector<int> dis=vector<int>(N,0x3f3f3f3f);

    vector<int> st=vector<int>(N,0);

    int n,m;

    int g[N][N];

    int dijkstra(int r){
        dis[r]=0;
        for(int i=0;i<n-1;i++){
            int j=-1;
            for(int k=1;k<=n;k++){
                if(!st[k]&&(j==-1||dis[j]>dis[k])){
                    j=k;
                }
            }
            for(int k=1;k<=n;k++){
                if(dis[j]+g[j][k]<dis[k]){
                    dis[k]=dis[j]+g[j][k];
                }
            }
            st[j]=1;
        }
        int res=-2;
        for(int i=1;i<=n;i++){
            if(dis[i]==0x3f3f3f3f){
                return -1;
            }else{
                res=max(res,dis[i]);
            }
        }
        return res;
    }

    int networkDelayTime(vector<vector<int>>& times, int q, int k) {
        n=q;
        m=0;
        memset(g,0x3f,sizeof g);
        while(m!=times.size()){
            g[times[m][0]][times[m][1]]=min(times[m][2],g[times[m][0]][times[m][1]]);
            m++;
        }
        return dijkstra(k);
    }
};

10.前k个高频单词

在这里插入图片描述

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int> mp;
        for(string ev: words) mp[ev]++;
        
        priority_queue<pair<int, string>> q;//大根堆,删大的留小,频数取相反就是留
        //大,然后字符串就是留小。。。相当于pair第一项排序和第二项排序相反的做法,不用自定义排序了呀!!
        for(auto [str, cnt]: mp){//*****
            q.push({-cnt, str});
            if(q.size() > k) q.pop();
        }
        vector<string> ans;
        while(!q.empty()){
            ans.push_back(q.top().second);
            q.pop();
        }
        reverse(ans.begin(), ans.end());//记得转过来
        return ans;
    }
};

三、Dijkstra

知识点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
st[]更确切的含义是某个点是否已经更新过其他点,而不是它的最短距离是否已经确定。

只用考虑有向图就行了

在这里插入图片描述

1.Dijkstra求最短路 I

在这里插入图片描述

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

int n,m;

const int N=510;

int g[N][N];//邻接矩阵
int dis[N];//原点到各个点最短距离
int st[N];//该点是否用过更新距离

int dijkstra(){
    memset(dis,0x3f,sizeof dis);//初始化距离
    dis[1]=0;//原点到自己的距离
    for(int i=0;i<n-1;i++){
        int t=-1;//初始是没找到
        for(int j=1;j<=n;j++){
            if(!st[j]&&(t==-1||dis[t]>dis[j])){//找距离原点最近的一个点
                t=j;
            }
        }
        
        for(int j=1;j<=n;j++){
            dis[j]=min(dis[j],dis[t]+g[t][j]);//用它去更新其他点到原点距离
        }
        
        st[t]=1;//表示用已经用该点更新过其他点到原点的最短距离了
    }
    if(dis[n]==0x3f3f3f3f) return -1;
    return dis[n];
}

int main(){
    cin>>n>>m;
    memset(g,0x3f,sizeof g);
    for(int i=0;i<m;i++){
        int r,l,w;
        cin>>r>>l>>w;
        g[r][l]=min(g[r][l],w);
    }
    cout<<dijkstra()<<endl;
}

2.Dijkstra求最短路 II

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int N=150010;

typedef pair<int,int> PII;

int n,m;

int h[N],w[N],e[N],ne[N],idx;

int dis[N];

int st[N];

void add(int a,int b,int c){
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

int dijkstra(){
    priority_queue<PII,vector<PII>,greater<PII>>heap;//存所有还没拿去更新的点,小根堆
    heap.push({0,1});
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    while(!heap.empty()){
        PII temp=heap.top();
        heap.pop();
        int ver=temp.second;//看距离原点最小的是哪个点
        if(!st[ver]){//看是不是应该拿过去更新了的点
            st[ver]=1//表示用过了
            int j;
            for(int i=h[ver];i!=-1;i=ne[i]){//i遍历的是idx,遍历拿去更新的点能连到的点,因为只有他们收到它影响
                j=e[i];//取出idx对应的编号
                if(dis[j]>w[i]+dis[ver]){
                    dis[j]=w[i]+dis[ver];
                    heap.push({dis[j],j});
                }
            }
        }
    }
    if(dis[n]==0x3f3f3f3f) return -1;
    return dis[n];
}

int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    int a,b,c;
    while(m--){
        cin>>a>>b>>c;
        add(a,b,c);//不用判断重边什么的,算法里面会判断
    }
    cout<<dijkstra()<<endl;
}

3.通信线路

在这里插入图片描述
在这里插入图片描述
题目要找的是第k+1大边的最小值嘛,二分是因为看所有可能的边的大小只要能满足比它大的边小于等于k就行,这样才能免单,为啥小于k的也要,因为题目要的是尽可能小的成本啊,只要成本够小管你是第几大的边,只要别超过k就行

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

int n,m,k;

const int N=1010,M=10010;

int st[N],dis[N];

int h[N],e[2*M],ne[2*M],w[2*M],idx;

int add(int a,int b,int c){
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}   

typedef pair<int,int> PII;

// bool check(int x){
//     memset(dis,0x3f,sizeof dis);
//     memset(st,0,sizeof st);
//     dis[1]=0;

//     priority_queue<PII,vector<PII>,greater<PII>> pque;
//     pque.push({0,1});

//     while(pque.size()){
//         auto hd=pque.top(); pque.pop();

//         int ver=hd.second;
//         if(st[ver]) continue;
//         st[ver]=true;

//         for(int i=h[ver];~i;i=ne[i]){
//             int go=e[i];
//             if(dis[go]>dis[ver]+(w[i]>x?1:0)){ // 如果是,贡献就是1
//                 dis[go]=dis[ver]+(w[i]>x?1:0);
//                 pque.push({dis[go],go});
//             }
//         }
//     }

//     return dis[n]<=k;
// }

bool check(int x){
    memset(dis,0x3f,sizeof dis);
    memset(st,0,sizeof st);
    dis[1]=0;

    queue<int>Q;
    Q.push(1);
    st[1]=1;
    while(Q.size()){
        auto hd=Q.front(); 
        Q.pop();
        st[hd]=0;
        int ver=hd;

        for(int i=h[ver];~i;i=ne[i]){
            int go=e[i];
            if(dis[go]>dis[ver]+(w[i]>x?1:0)){ // 如果是,贡献就是1
                dis[go]=dis[ver]+(w[i]>x?1:0);
                if(!st[go]){
                    Q.push(go);
                    st[go]=1;
                }
                
            }
        }
    }

    return dis[n]<=k;
}

int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m>>k;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    int l=0,r=1e6+1;
    while(l<r){
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    if(r==1e6+1) cout<<"-1";
    else cout<<r;
}

三、SPFA

知识点

在这里插入图片描述
在这里插入图片描述

1.spfa求最短路

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int N=100010;

int n,m;

int st[N];

int dis[N];

int h[N],e[N],ne[N],idx,w[N];

int add(int a,int b,int c){
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

int dijkstra(){
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    
    queue<int>Q;
    Q.push(1);
    st[1]=1;
    while(!Q.empty()){
        int t=Q.front();
        Q.pop();
        st[t]=0;
        for(int i=h[t];~i;i=ne[i]){
            int j=e[i];
            if(dis[j]>dis[t]+w[i]){
                dis[j]=dis[t]+w[i];
                if(!st[j]){
                    Q.push(j);
                    st[j]=1;
                }
            }
        }
    }
    return dis[n];
}

int main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        
    }
    int res;
    res=dijkstra();
    if(res==0x3f3f3f3f){
        cout<<"impossible";
    }else{
        cout<<res;
    }
}

2.spfa判断负环

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

const int N=2010,M=10010;

int n,m;

int st[N];

int dis[N],cnt[N];

int h[N],e[M],ne[M],w[M],idx;

int add(int a,int b,int c){
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

bool spfa(){
    queue<int> Q;
    for(int i=1;i<=n;i++){
        Q.push(i);
        st[i]=1;
    }
    
    while(Q.size()){
        int t=Q.front();
        Q.pop();
        st[t]=0;
        for(int i=h[t];~i;i=ne[i]){
            int j=e[i];
            if(dis[j]>dis[t]+w[i]){
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return true;
                if(!st[j]){
                    Q.push(j);
                    st[j]=1;
                }
            }
        }
    }
    return false;
}

int main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    if(spfa()){
        cout<<"Yes";
    }else{
        cout<<"No";
    }
}

3.道路和航线

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>

using namespace std;

int n,m1,m2,k;

const int N=25010,M=150010;

int h[N],e[M],ne[M],w[M],idx;

int st[N],dis[N];

int add(int a,int b,int c){
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

void spfa(int x){
    memset(dis,0x3f,sizeof dis);
    memset(st,0,sizeof st);//放里面保险点,免得忘记初始化
    deque<int>Q;//双端队列
    dis[x]=0;
    st[x]=1;
    Q.push_back(x);
    while(Q.size()){
        int t=Q.front();
        Q.pop_front();
        st[t]=0;
        for(int i=h[t];~i;i=ne[i]){
            int j=e[i];
            if(dis[j]>dis[t]+w[i]){
                dis[j]=dis[t]+w[i];
                if(!st[j]){
                    if(Q.size()&&dis[j]<dis[Q.front()]){
                    //SLF优化
                    //但是对于USACO的题目而言,我们发现他们居然恶心地卡SPFA算法,那么我们不得不使用一些玄学优化.
                    //对于SPFA算法而言,它的优化有两种,我们今天使用SLF优化算法.众所周知,SPFA算法是一种鉴于队列的实现算法.每一次有节点加入队列都是加入队尾.但是SLF优化,不同于一
                    //般的SPFA算法,它是一种利用双端队列算法处理的问题.如果说当前点所花费的值少于我们当前队头点的值的话,那么我们就将这个节点插入到队头去,否则我们还是插入到队尾.这个就是非常好用的SLF优化算法.
                        Q.push_front(j);
                    }
                    else{
                        Q.push_back(j);
                    }
                    st[j]=1;
                }
            }
        }
    }
}

int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m1>>m2>>k;
    while(m1--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
        
    }
    while(m2--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    spfa(k);
    for(int i=1;i<=n;i++){
        if(dis[i]>=0x3f3f3f3f/2) cout<<"NO PATH"<<endl;//防止负权边偷偷松弛
        else cout<<dis[i]<<endl;
    }
}

4.通信线路

在这里插入图片描述
在这里插入图片描述
题目要找的是第k+1大边的最小值嘛,二分是因为看所有可能的边的大小只要能满足比它大的边小于等于k就行,这样才能免单,为啥小于k的也要,因为题目要的是尽可能小的成本啊,只要成本够小管你是第几大的边,只要别超过k就行

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

int n,m,k;

const int N=1010,M=10010;

int st[N],dis[N];

int h[N],e[2*M],ne[2*M],w[2*M],idx;

int add(int a,int b,int c){
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}   

typedef pair<int,int> PII;

// bool check(int x){
//     memset(dis,0x3f,sizeof dis);
//     memset(st,0,sizeof st);
//     dis[1]=0;

//     priority_queue<PII,vector<PII>,greater<PII>> pque;
//     pque.push({0,1});

//     while(pque.size()){
//         auto hd=pque.top(); pque.pop();

//         int ver=hd.second;
//         if(st[ver]) continue;
//         st[ver]=true;

//         for(int i=h[ver];~i;i=ne[i]){
//             int go=e[i];
//             if(dis[go]>dis[ver]+(w[i]>x?1:0)){ // 如果是,贡献就是1
//                 dis[go]=dis[ver]+(w[i]>x?1:0);
//                 pque.push({dis[go],go});
//             }
//         }
//     }

//     return dis[n]<=k;
// }

bool check(int x){
    memset(dis,0x3f,sizeof dis);
    memset(st,0,sizeof st);
    dis[1]=0;

    queue<int>Q;
    Q.push(1);
    st[1]=1;
    while(Q.size()){
        auto hd=Q.front(); 
        Q.pop();
        st[hd]=0;
        int ver=hd;

        for(int i=h[ver];~i;i=ne[i]){
            int go=e[i];
            if(dis[go]>dis[ver]+(w[i]>x?1:0)){ // 如果是,贡献就是1
                dis[go]=dis[ver]+(w[i]>x?1:0);
                if(!st[go]){
                    Q.push(go);
                    st[go]=1;
                }
                
            }
        }
    }

    return dis[n]<=k;
}

int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m>>k;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    int l=0,r=1e6+1;
    while(l<r){
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    if(r==1e6+1) cout<<"-1";
    else cout<<r;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值