分层图

Revamping Trails G

板。

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;
}

Grass Cownoisseur G

思路是:先缩点,缩点之后会形成一个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;
}
posted @ 2023-08-28 21:15  XYini  阅读(12)  评论(0)    收藏  举报