洛谷月赛

第一题 很水
第二题 由题意得路径一定没有环;
跑三遍dij求出三个给定点到任意点的距离,然后枚举分叉点;

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e6+7;
struct node{
	int id;
}s[N];
struct edge{
	int v,nxt;
}e[N<<2];
int n,m,a,b,c,cnt,st,ed1,ed2;
long long ans=1e15;
int head[N],w[N],vis[N],pre[N];
long long dis[3][N];
void add_edge(int u,int v){
	e[++cnt]=(edge){v,head[u]};
	head[u]=cnt;
}
/*
void spfa(){
	memset(dis,0x7f,sizeof(dis));
	queue<int> q;
	q.push(st);
	vis[st]=1;
	dis[st]=w[st];
	while(q.size()){
		int now=q.front();
		q.pop();
		vis[now]=0;
		for(int i=head[now];i;i=e[i].nxt){
			int to=e[i].v;
			if(dis[to]>dis[now]+w[to]){
				dis[to]=dis[now]+w[to];
				pre[to]=now;
				if(!vis[to]){
					q.push(to);
					vis[to]=1;
				}
			}
		}
	}
}
*/
void dij(int tt,int x){
	priority_queue<pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > >q;
	memset(vis,0,sizeof(vis));
	q.push(make_pair(w[x],x));
//	vis[x]=1;
	dis[tt][x]=w[x];
	while(q.size()){
		int now=q.top().second;
		q.pop();
		if(vis[now]) continue;
		vis[now]=1;
//		cout<<"-->"<<now<<"\n";
		for(int i=head[now];i;i=e[i].nxt){
			int to=e[i].v;
//			cout<<dis[tt][to]<<"\n";
			if(dis[tt][now]+w[to]<dis[tt][to]){
//				cout<<now<<" "<<to<<"\n";
//				cout<<dis[tt][now]+w[to]<<"\n";
				dis[tt][to]=dis[tt][now]+w[to];
				q.push(make_pair(dis[tt][to],to));
			}
		}
	}
}
int main(){
	scanf("%d%d%d%d%d",&n,&m,&a,&b,&c);
	st=a;
	ed1=n*(n-1)+b;
	ed2=n*(n-1)+c; 
	for(int i=1;i<=n*m;i++){
		scanf("%d",&w[i]);	
		s[i].id=i;
	}
	for(int i=1;i<=n*m;i++){
		int shang=s[i].id-n;
		int xia=s[i].id+n;
		int zuo=s[i].id-1;
		int you=s[i].id+1;
		if(shang>=1&&shang<=n*m) add_edge(s[i].id,shang);
		if(xia>=1&&xia<=n*m) add_edge(s[i].id,xia);
		if(zuo>=1&&zuo<=n*m&&zuo%n!=0) add_edge(s[i].id,zuo);
		if(you>=1&&you<=n*m&&you%n!=1) add_edge(s[i].id,you);
	}
	memset(dis,0x7f,sizeof(dis));
//	cout<<ans;
//	cout<<dis[1][1];
	dij(0,st);
	dij(1,ed1);
	dij(2,ed2);
//	cout<<dis[ed1];
//	for(int i=1;i<=n*m;i++){
//		cout<<dis[0][i]<<" "<<dis[1][i]<<" "<<dis[2][i]<<"\n"; 
//	}
	for(int i=1;i<=n*m;i++){
//		cout<<dis[1][i]<<" "<<dis[2][i]<<" "<<dis[3][i]<<"\n";
		ans=min(dis[0][i]+dis[1][i]+dis[2][i]-2*w[i],ans);
	}
	cout<<ans;
}
posted @ 2020-09-19 21:32  Aswert  阅读(137)  评论(0编辑  收藏  举报