最短路Ⅰ

基础知识懒得写。水题都放在这里的哦。

***集合

评价一个字,水。能评上蓝题说实话有一点侮辱 \(A+B\) \(problem\)。数据范围小,写起简单,还能评上蓝题。这样的题目给我再来一打如何。

#include<cstdio>
#include<cstring>
//#define zczc
using namespace std;
const int N=41;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
    wh*=f;return;
}
inline void check(int &s1,int s2){
	if(s1>s2)s1=s2;return; 
}

int m,n,q,d[N],a[N][N];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	int s1,s2;
	read(m);read(n);
	memset(a,0x3f,sizeof(a));
	for(int i=1;i<=n;i++){
		read(s1);read(s2);
		a[s1][s2]=a[s2][s1]=1;
	}
	for(int i=1;i<=m;i++){
		a[i][i]=0;
		for(int j=1;j<=m;j++){
			for(int k=1;k<=m;k++){
				check(a[j][k],a[j][i]+a[i][k]);
			}
		}
	}
	read(q);
	while(q--){
		read(s1);read(s2);
		for(int i=1;i<=m;i++){
			if(a[s1][i]+a[i][s2]==a[s1][s2]){
				printf("%d ",i);
			}
		}
		putchar('\n');
	}
	
	return 0;
}

集合位置

又是集合?

一句话概括,求图的次短路。

一开始做这道题的时候,内心慌得一批,当时写严格次小生成树时写了大半天,而一般来说,树上问题转到图上之后,难度会大幅增加……

不过事实证明,我的担心是多余的。这就是一道模板题,而且特别简单,原因有二,一是因为它是“次小”,而不是“严格次小”;二是因为它数据范围很小,严格次小生成树要求使用 \(O(N logN)\) 的算法,而这道题用 \(O(N^2logN)\) 都能过。那就简单了啊。直接枚举最短路上的每一条边,删去,再跑一遍最短路即可。

#include<cstdio>
#include<cmath>
#include<iostream> 
#include<cstring>
#include<queue>
//#define zczc
using namespace std;
const int N=210;
const int M=N*N;
const double Max=1e9;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
    wh*=f;return;
}

int m,n;
struct point{
	double x,y;
}a[N];
inline double operator &(point s1,point s2){
	double d1=s1.x-s2.x,d2=s1.y-s2.y;
	return sqrt(d1*d1+d2*d2);
}
struct edge{
	int f,t,next;
	double v;
}e[M];
int esum,head[N];
inline void add(int fr,int to,double val){
	esum++;
	e[esum].t=to;
	e[esum].f=fr;
	e[esum].v=val;
	e[esum].next=head[fr];
	head[fr]=esum;
}

double ans=Max,dis[N];
int come[N];
bool vis[N];
struct node{
	int num;
	double dis; 
};
inline bool operator <(node s1,node s2){
	return s2.dis<s1.dis;
}
priority_queue<node>q;
void solve(int ch,bool fir){
	while(!q.empty())q.pop();
	for(int i=1;i<=m;i++)dis[i]=Max;
	memset(vis,false,sizeof(vis));
	dis[1]=0;q.push((node){1,0});
	while(!q.empty()){
		node now=q.top();q.pop();
		int wh=now.num;double nd=now.dis;
		if(vis[wh])continue;vis[wh]=true;
		for(int i=head[wh],th;i;i=e[i].next){
			if(i==ch)continue;
			th=e[i].t;
			if(dis[wh]+e[i].v<dis[th]){
				if(fir)come[th]=i;
				dis[th]=dis[wh]+e[i].v;
				q.push((node){th,dis[th]});
			}
		}
	}
	if(!fir){
		if(ans>dis[m])ans=dis[m];
	}
	return;
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	int s1,s2;
	read(m);read(n);
	for(int i=1;i<=m;i++){
		cin>>a[i].x>>a[i].y;
	}
	for(int i=1;i<=n;i++){
		read(s1);read(s2);
		add(s1,s2,a[s1]&a[s2]);
		add(s2,s1,a[s1]&a[s2]);
	}
	
	solve(0,true);
	int now=m;
	while(now){
		if(come[now])solve(come[now],false);
		else break;
		now=e[come[now]].f;
	}
	if(ans>Max-1)printf("-1");
	else printf("%.2f",ans);
	
	return 0;
}
posted @ 2021-08-16 20:12  Feyn618  阅读(20)  评论(0编辑  收藏  举报