【题目分析】
大意就是有一张图,边权有两个值,ai和bi
找到一条路径,使得路径上的max(ai)+max(bi)最小。
遇到有两个权值或者多个权值的时候,如果他们互相影响,试着用分块搞一搞。
如果互不影响,先用排序搞掉一维。
这显然a与b分开计算,直接按照ai排序。
之后不断加入,然后计算在bi上的最短路,更新答案即可。
SPFA代码相当好写(复杂度一直是玄学如果重边比较多,几乎可以达到nm)
这么玄学的复杂度居然AC了,真实神奇。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 300005
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
void Finout()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
}
int Getint()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m,dis[maxn],ans=inf;
struct edge{int l,r,a,b;}e[maxn];
bool cmp(edge x,edge y)
{return x.a<y.a;}
int h[maxn<<1],ne[maxn<<1],to[maxn<<1],w[maxn<<1],en=0;
void add(int a,int b,int c)
{
to[en]=b; w[en]=c; ne[en]=h[a]; h[a]=en++;
to[en]=a; w[en]=c; ne[en]=h[b]; h[b]=en++;
}
int inq[maxn];
queue <int> q;
void SPFA(int S)
{
while (!q.empty()) q.pop();
q.push(S);
while (!q.empty())
{
int x=q.front();q.pop();inq[x]=0;
// cout<<"on "<<x<<endl;
for (int i=h[x];i>=0;i=ne[i])
{
if (dis[to[i]]>max(dis[x],w[i]))
{
dis[to[i]]=max(dis[x],w[i]);
if (!inq[to[i]])
{
inq[to[i]]=1;
q.push(to[i]);
}
}
}
}
}
int main()
{
Finout();
n=Getint(); m=Getint();
F(i,1,m)
{
e[i].l=Getint();
e[i].r=Getint();
e[i].a=Getint();
e[i].b=Getint();
}
sort(e+1,e+m+1,cmp);
memset(h,-1,sizeof h);
memset(dis,0x3f,sizeof dis);
dis[1]=0;
F(i,1,m)
{
add(e[i].l,e[i].r,e[i].b);
SPFA(e[i].l);SPFA(e[i].r);
ans=min(ans,dis[n]+e[i].a);
}
if (ans==inf) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
之后想一想,用LCT去维护边权貌似复杂度更好。
也是按照ai排序,然后加入边,如果构成环,就删去权值最大的一个。
然后统计答案。
维护边权的时候,直接维护比较难,可以把原图边和点都看作点,然后互相连接,这样就只有点权了。
写起来也很爽。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 500005
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
void Finout()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
}
int Getint()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int mx[maxn],v[maxn],n,m,ans=inf,sta[maxn],top=0;
int fa[maxn],ch[maxn][2],rev[maxn],val[maxn];
struct edge{int u,v,a,b;}e[maxn];
bool cmp(edge x,edge y){return x.a<y.a;}
bool isroot(int x)
{return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void update(int x)
{
mx[x]=x;
if (val[mx[ch[x][0]]]>val[mx[x]]) mx[x]=mx[ch[x][0]];
if (val[mx[ch[x][1]]]>val[mx[x]]) mx[x]=mx[ch[x][1]];
}
void pushdown(int x)
{
if (rev[x])
{
rev[x]^=1;
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0; else l=1;
r=l^1;
if (!isroot(y))
{
if (ch[z][0]==y) ch[z][0]=x;
else ch[z][1]=x;
}
fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
ch[y][l]=ch[x][r]; ch[x][r]=y;
update(y);update(x);
}
void splay(int x)
{
top=0;sta[++top]=x;
for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
while (top) pushdown(sta[top--]);
while (!isroot(x))
{
int y=fa[x],z=fa[y];
if (!isroot(y))
{
if (ch[y][0]==x^ch[z][0]==y) rot(y);
else rot(x);
}
rot(x);
}
}
void access(int x)
{
for (int t=0;x;t=x,x=fa[x])
splay(x),ch[x][1]=t,update(x);
}
void makeroot(int x)
{
access(x);
splay(x);
rev[x]^=1;
}
int find(int x)
{
access(x);
splay(x);
while (ch[x][0]) x=ch[x][0];
return x;
}
void link(int x,int y)
{
makeroot(x);
fa[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y);
if (ch[y][0]==x)
{
ch[y][0]=x;
fa[x]=0;
}
}
int query(int x,int y)
{
makeroot(x);
access(y);
splay(y);
return mx[y];
}
int main()
{
Finout();
val[0]=-inf;
n=Getint();m=Getint();
F(i,1,n) val[i]=-inf;
F(i,1,m)
{
e[i].u=Getint();
e[i].v=Getint();
e[i].a=Getint();
e[i].b=Getint();
}
sort(e+1,e+m+1,cmp);
F(i,1,m)
{
int l=e[i].u,r=e[i].v,a=e[i].a,b=e[i].b;
int flag=0;
// cout<<l<<" "<<r<<" "<<a<<" "<<b<<endl;
if (find(l)==find(r))
{
int tmp=query(l,r);
if (val[tmp]>b)
{
// cout<<"cut "<<tmp<<" "<<e[tmp-n].v<<" "<<e[tmp-n].u<<endl;
cut(tmp,e[tmp-n].v);
cut(tmp,e[tmp-n].u);
flag=1;
}
else
{
// cout<<"cal"<<endl;
if (find(1)==find(n))
{
ans=min(ans,a+val[query(1,n)]);
continue;
}
}
}
else flag=1;
if (flag)
{
// cout<<"link"<<endl;
link(l,n+i);link(r,n+i);
val[n+i]=e[i].b;
mx[n+i]=n+i;
}
if (find(1)==find(n))
{
// cout<<"cal"<<endl;
ans=min(ans,a+val[query(1,n)]);
}
}
if (ans==inf) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
转载于:https://www.cnblogs.com/SfailSth/p/6294832.html