P8724 [蓝桥杯 2020 省 AB3] 限高杆(分层图)

· · 个人记录

分层图。

考虑建分层图,因为题目只说加2条边,所以我们可以建3个图,我们加边时,可以将第一层图的点u连到下一层图的点v上,因为只用加两条边,所以我们建三层图完全够用。

注意这里要建单向边,因为你不能从下面的图走到上面。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<set>

using namespace std;

#define int long long
#define ll long long
#define Endl cout<<endl;
#define ENdl Endl
#define xy cout<<"xy";
#define yx cout<<"yx";
#define pii pair<int,int>
#define lowbit(x) x&(-x)
#define fi first
#define se second
#define fst ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'

const int N=2e5+10;//注意修改
const int mod=1e9+7;
const int Max=0x3f3f3f3f3f3f3f;

vector<pii> ve[N*3];

int n,m;
struct node{
    int a,b,c,d;
}a[N];
int vis[30005];
int dis[30005];
struct id{
    int p,d;
    bool operator < (const id &b)const{
        return d>b.d;
    }
};
void dij(int s){
    memset(vis,0,sizeof vis);
    memset(dis,0x3f,sizeof dis);
    dis[s]=0;
    priority_queue<id> q;
    q.push({s,0});
    while(!q.empty()){
        int u=q.top().p;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(auto v:ve[u]){
            if(dis[v.fi]>dis[u]+v.se){
                dis[v.fi]=dis[u]+v.se;
                q.push({v.fi,dis[v.fi]});
            }
        }
    }
}

signed main(){

//   freopen("a.in","r",stdin);
//   freopen("a.out","w",stdout);
    fst
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a[i].a>>a[i].b>>a[i].c>>a[i].d;
        if(a[i].d==0){
            ve[a[i].a].push_back({a[i].b,a[i].c});
            ve[a[i].b].push_back({a[i].a,a[i].c});
        }
    }
    dij(1);
    // for(int i=1;i<=n;i++){
    //     cout<<dis[i]<<' ';
    // }
    // cout<<endl;
    int dis1=dis[n];
    for(int i=1;i<=n;i++) ve[i].clear();
    for(int i=1;i<=m;i++){
        if(a[i].d==1){
            for(int j=0;j<=1;j++){
                ve[a[i].a+j*n].push_back({a[i].b+(j+1)*n,a[i].c});
                //ve[a[i].b+(j)*n].push_back({a[i].a+(j+1)*n,a[i].c});
            }
        }else{
            for(int j=0;j<=2;j++){
                ve[a[i].a+j*n].push_back({a[i].b+j*n,a[i].c});
                ve[a[i].b+j*n].push_back({a[i].a+j*n,a[i].c});
            }
        }
    }
    dij(1);
    int dis2=min({dis[n],dis[2*n],dis[3*n]});
    cout<<dis1-dis2;
    return 0;
}