ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

道路拆除

2021-01-24 16:01:03  阅读:180  来源: 互联网

标签:cnt include int edge 道路 path 拆除 maxn


$ \textbf 道路拆除 $

Emm......标题行过长是什么意思啊?管理员还是给我过一下吧~毕竟是我第一次交题解,难免会出错qwq

$ \textbf 前言 $


昨天晚上和机房同学( 椋枨 )一起水题,发现了这道去年普及组的图论题目,于是就准备开始水想不到20min钟就敲完了QwQ......

结果我刚过样例,交上去全WA了......我写的是堆优化的dijkstra,椋枨写的是线段树优化的(%%%%%)。想不到椋枨过了样例以后交上去是85分,唉,我还是太蒟蒻了/捂脸哭

于是我就开始了漫长找BUG......最后发现有一个字母打错了,然鹅样例还过了qwq真的很神奇额

不过我交上去也是85分,于是又重新构思写了一遍,终于AC了!/捂脸哭

$ \textbf{85 · scores code} $

这个代码的思想就是以1为起点,跑一遍最短路,记录下路径。然后以s1为终点,按照记录下的路径向前,一直到一,然后把经过的点标记为true。再以s2为终点向前到一,如果中间有某一个点是true,就退出,然后记录下此时s1和s2向前的路径的数量ans,用m-ans得到答案。那么为什么一向前搜索到true就退出呢?原因很简单——如果在s2向前的过程中遇到的点在s1向前的过程中出现过,说明这个点(包括之前的路径)在两条路径中都重合了。那么如果不退出的话,就会重复。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

#define maxn 100010

struct Edge{
	int start;
	int to;
	int val;
	int nexty;
}edge[maxn];//结构体存图 

int link[maxn],path[maxn],path2[maxn],path3[maxn],pre[maxn]/*记录路径的起点*/,preval[maxn],n,m,u,v,w,x,y,z,s1,t1,s2,t2,cnt,ans;
bool vis[maxn],vis2[maxn];

void build(int u,int v,int w){//标准前向星存边 
	edge[cnt].start=u;
	edge[++cnt].to=v;
	edge[cnt].val=w;
	edge[cnt].nexty=link[u];
	link[u]=cnt;
}

void dijkstra(int s/*起点*/){
	memset(path,0x3f3f3f3f,sizeof path);
	memset(vis,false,sizeof vis);
	memset(pre,0,sizeof pre);
	//勿忘清零! 
	path[s]=0;
	priority_queue< pair< int,int > > q;//堆优化 
	q.push(make_pair(0,s));
	while(!q.empty()){
		int x=q.top().second;
		q.pop();
		if(vis[x])continue;
		vis[x]=1;
		for(int i=link[x];i;i=edge[i].nexty){
			if(path[edge[i].to]>path[x]+edge[i].val){
				path[edge[i].to]=path[x]+edge[i].val;
				pre[edge[i].to]=x;
				q.push(make_pair(-path[edge[i].to/*负号实现小根堆*/],edge[i].to));
			}
		}
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&u,&v);
		build(u,v,1);
		build(v,u,1);
	}
	scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
	dijkstra(1);
	if(path[s1]>t1){
		printf("-1\n");
		return 0;
	}
	else if(path[s2]>t2){
		printf("-1\n");
		return 0;
	}
	for(int i=s2;i;i=pre[i]){//向前 
		ans++;
		vis2[i]=true;
	}
	ans--;
	for(int i=s1;i;i=pre[i]){//向前 
		if(vis2[i]==true){
			break;
		}
		ans++;
	}
	/*
	for(int i=1;i<=n;i++){
		if(path[i]+path2[i]+path3[i]<min1){
			min1=path[i]+path2[i]+path3[i];
			ii=i;
		}
	}
	*/
	printf("%d",m-ans);
	return 0;
}

$ \textbf {AC·code} $

正解的主要思路就是以已知的三个点为起点,分别跑一遍最短路,记录每个点到已知的三个点的距离,如果符合要求,说明这是两条路径上重复的点,就update一次ans,最后输出m-ans就OK了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

#define maxn 100010

struct Edge{
	int start;
	int to;
	int val;
	int nexty;
}edge[maxn];//结构体存图 

int link[maxn],path[maxn],path2[maxn],path3[maxn],pre[maxn]/*记录路径的起点*/,n,m,u,v,w,x,y,z,s1,t1,s2,t2,cnt,ans;
bool vis[maxn];

void build(int u,int v,int w){//标准前向星存边 
	edge[cnt].start=u;
	edge[++cnt].to=v;
	edge[cnt].val=w;
	edge[cnt].nexty=link[u];
	link[u]=cnt;
}

void dijkstra(int s/*起点*/){
	memset(path,0x3f3f3f3f,sizeof path);
	memset(vis,false,sizeof vis);
	//勿忘清零! 
	path[s]=0;
	priority_queue< pair< int,int > > q;//堆优化 
	q.push(make_pair(0,s));
	while(!q.empty()){
		int x=q.top().second;
		q.pop();
		if(vis[x])continue;
		vis[x]=1;
		for(int i=link[x];i;i=edge[i].nexty){
			if(path[edge[i].to]>path[x]+edge[i].val){
				path[edge[i].to]=path[x]+edge[i].val;
				pre[edge[i].to]=x;
				q.push(make_pair(-path[edge[i].to/*负号实现小根堆*/],edge[i].to));
			}
		}
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&u,&v);
		build(u,v,1);
		build(v,u,1);
	}
	scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
	dijkstra(s1);
	for(int i=1;i<=n;i++){
		path2[i]=path[i];
	}
	dijkstra(s2);
	for(int i=1;i<=n;i++){
		path3[i]=path[i];
	}
	dijkstra(1);
	int ans=0x3f3f3f3f;
	for(int i=1;i<=n;i++){
		if(path[i]+path2[i]<=t1&&path[i]+path3[i]<=t2){
			ans=min(ans,path[i]+path2[i]+path3[i]);//更新ans 
		}
	}
	if(ans==0x3f3f3f3f){//如果不符合要求,输出-1 
		printf("-1");
	}
	else printf("%d",m-ans);
	return 0;
}

标签:cnt,include,int,edge,道路,path,拆除,maxn
来源: https://www.cnblogs.com/Jair314/p/14321165.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有