P8724 [蓝桥杯 2020 省 AB3] 限高杆(分层图)
__S08577__ · · 个人记录
分层图。
考虑建分层图,因为题目只说加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;
}