分层图
板。
code:
const int N=1e6+10;
int n,m,k,x,y,z,cnt,head[N],dis[N],vis[N];
struct node{
int u,v,w,nxt;
}a[N<<3];
void add(int u,int v,int w){
a[++cnt]=(node){u,v,w,head[u]};
head[u]=cnt;
}
priority_queue<pair<int,int> , vector<pair<int,int> > ,greater<pair<int,int> > >q;
void dij(int x){
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
q.push(make_pair(0,x));
while(!q.empty()){
int now=q.top().second;
q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=head[now];i;i=a[i].nxt){
int v=a[i].v;
if(dis[v]>dis[now]+a[i].w){
dis[v]=dis[now]+a[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
n=read(); m=read(); k=read();
for(int i=1;i<=m;++i) {
x=read();y=read();z=read();
add(x,y,z);
add(y,x,z);
for(int j=1;j<=k;++j) {
add(x+(j*n),y+(j*n),z);
add(y+(j*n),x+(j*n),z);
add(x+((j-1)*n),y+(j*n),0);
add(y+((j-1)*n),x+(j*n),0);
}
}
for(int i=1;i<=k;++i) {
add(n+((i-1)*n),n+(i*n),0);
}
dij(1);
cout<<dis[n+(k*n)];
return 0;
}
板+1。
code:
const int N=1e6+10;
const int M=3e6+10;
int n,m,s,e,k,x,y,z,cnt,head[N*10],dis[N*10],vis[N*10];
struct node{
int u,v,w,nxt;
}a[M];
void add(int u,int v,int w){
a[++cnt]=(node){u,v,w,head[u]};
head[u]=cnt;
}
priority_queue<pair<int,int> ,vector<pair<int,int> > ,greater<pair<int,int> > >q;
void dij(int x){
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
q.push(make_pair(0,x));
while(!q.empty()){
int now=q.top().second;
q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=head[now];i;i=a[i].nxt){
int v=a[i].v;
if(dis[v]>dis[now]+a[i].w){
dis[v]=dis[now]+a[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
signed main(){
n=read(); m=read(); k=read();
s=read(); e=read();
for(int i=1;i<=m;++i) {
x=read(); y=read(); z=read();
add(x,y,z);
add(y,x,z);
for(int j=1;j<=k;++j) {
add(x+(j*n),y+(j*n),z);
add(y+(j*n),x+(j*n),z);
add(x+((j-1)*n),y+(j*n),0);
add(y+((j-1)*n),x+(j*n),0);
}
}
for(int i=1;i<=k;++i) {
add(e+(i-1)*n,e+i*n,0);//把终点连起来,可以使答案的最小值传递
}
dij(s);
cout<<dis[e+(k*n)];
return 0;
}
思路大概是,横向边一层,纵向边一层,转折点将两层进行连接。
code:
const int N=1e6+10;
int n,m,cnt,s,e,head[N],dis[N],vis[N];
struct node{
int u,v,w,nxt;
}a[N<<1];
struct Node{
int x,y,id;
}p[N];
void add(int u,int v,int w){
a[++cnt]=(node){u,v,w,head[u]};
head[u]=cnt;
}
/*
下横上纵
横1-n 纵n+1-2+n
*/
int cmp1(Node xx,Node yy){
if(xx.x==yy.x) return xx.y<yy.y;
return xx.x<yy.x;
}
int cmp2(Node xx,Node yy){
if(xx.y==yy.y)return xx.x<yy.x;
return xx.y<yy.y;
}
void ins(int from,int to,int val)
{add(from,to,val);add(to,from,val);}
priority_queue<pair<int,int> ,vector<pair<int,int> > ,greater<pair<int,int> > >q;
void dij(int x) {
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
q.push(make_pair(0,x));
while(!q.empty()){
int now=q.top().second;
q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=head[now];i;i=a[i].nxt){
int v=a[i].v;
if(dis[v]>dis[now]+a[i].w) {
dis[v]=dis[now]+a[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
n=read(); m=read();
s=m+1; e=m+2;
for(int i=1;i<=m+2;++i) {
p[i].x=read(); p[i].y=read();
p[i].id=i;
}
sort(p+1,p+3+m,cmp1);
for(int i=2;i<=m+2;++i) {
if(p[i].x==p[i-1].x) {
add(p[i].id,p[i-1].id,(p[i].y-p[i-1].y)<<1);
add(p[i-1].id,p[i].id,(p[i].y-p[i-1].y)<<1);
}
}
sort(p+1,p+3+m,cmp2);
for(int i=2;i<=m+2;++i) {
if(p[i].y==p[i-1].y) {
add(p[i].id+m+2,p[i-1].id+m+2,(p[i].x-p[i-1].x)<<1);
add(p[i-1].id+m+2,p[i].id+m+2,(p[i].x-p[i-1].x)<<1);
}
}
for(int i=1;i<=m;i++)
ins(i,i+m+2,1);
ins(m+1,m*2+3,0);ins(m+2,m*2+4,0);
dij(s);
if(dis[e]==1061109567){
cout<<"-1"<<'\n';
}
else
cout<<dis[e];
return 0;
}
思路是:先缩点,缩点之后会形成一个DAG。
由于只能逆行一次,所以建立两层图,只能单向从一个图的 \(v\) 连向另一个图层的该边的 \(u\)。
然后跑 spfa 求最长路。
code:
const int N=1e6+10;
int n,m,cnt,x[N],y[N],head[N],vis[N],sta[N],sc;
int tot,low[N],dfn[N],siz[N],num[N],Num,dis[N];
struct node{
int u,v,nxt;
}a[N];
/*
缩点+分层图
分为两层
第一层为原图
两层之间由第一层的终止点连向下一层该点的起始点
*/
void add(int u,int v){
a[++cnt]=(node){u,v,head[u]};
head[u]=cnt;
}
void tarjan(int x){
dfn[x]=low[x]=++tot;
sta[++sc]=x;vis[x]=1;
for(int i=head[x];i;i=a[i].nxt){
if(!dfn[a[i].v])tarjan(a[i].v),low[x]=min(low[x],low[a[i].v]);
else if(vis[a[i].v]) low[x]=min(low[x],dfn[a[i].v]);
}
if(low[x]==dfn[x]){
int Top=sta[sc--];
vis[Top]=0;
num[Top]=++Num;
siz[Num]++;
while(Top!=x){
Top=sta[sc--];
vis[Top]=0;
num[Top]=Num;
siz[Num]++;
}
}
}
queue<int>q;
void spfa(int x){
q.push(x);
while(!q.empty()){
int now=q.front();
q.pop();
vis[now]=0;
for(int i=head[now];i;i=a[i].nxt){
int v=a[i].v;
if(dis[v]<dis[now]+siz[now]) {
dis[v]=dis[now]+siz[now];
if(!vis[v]) q.push(v);
}
}
}
}
int main(){
n=read();m=read();
for(int i=1;i<=m;++i) {
x[i]=read();y[i]=read();
add(x[i],y[i]);
}
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
cnt=0;
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
for(int i=1;i<=m;++i) {
int u=num[x[i]],v=num[y[i]];
if(u!=v) {
add(u,v);
add(u+Num,v+Num);
add(v,u+Num);
}
}
for(int i=1;i<=Num;++i) siz[i+Num]=siz[i];
spfa(num[1]);
cout<<dis[num[1]+Num];
return 0;
}

浙公网安备 33010602011771号