JZOJ 4671.【提高A组模拟赛 T1】 World Tour

41 篇文章 0 订阅
8 篇文章 0 订阅

题目大意:

给出一个有向图,从第i个点到第j个点XX只会走最短路,问去哪四个城市使得他走的路最长。

解题思路:

bfs求多源最短路,然后求出对于每个点来说的距离它最远的点和次远的点,反最远点和反次远点。

之后枚举中间两个点,然后如果最远的相同就一个用次远,否则都用最远。

A c c e p t e d   c o d e Accepted\ code Accepted code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

const int N = 5100;
const int M = 10100; 

struct edge {
	int to, next; 
}a[M]; 

int n, tot, m, maxs, ls[N]; 
int f[N][N], disnd[N], disnd2[N], disst[N], disst2[N], ans[4];

std::queue <int>  q;

void adde(int x, int y) {
	a[++tot].to = y;  a[tot].next = ls[x];  ls[x] = tot;
}

void bfs(int s) {
	q.push(s); f[s][s] = 0;
	while(!q.empty()) {
		int x = q.front(); q.pop();
		for(int i = ls[x]; i; i = a[i].next) {
			int y = a[i].to;
			if(f[s][y] < 0) {
				f[s][y] = f[s][x] + 1;
				q.push(y);
			}
		}
	}
}

int main() {
	memset(f, 0xcf, sizeof(f));
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= m; ++i) {
		int x, y; 
		scanf("%d %d", &x, &y);
		adde(x, y); 
	}
	for(int i = 1; i <= n; ++i)
		bfs(i);
	for(int i = 1; i <= n; ++i) {
	    for(int j = 1; j <= n; ++j)
			if (i != j) {
		    	if(f[i][j] > f[i][disst[i]]){
		    		disst2[i] = disst[i];
		    		disst[i] = j;
		    	}
		    	else if(f[i][j] > f[i][disst2[i]])
		    		     disst2[i] = j;
		    }
	}
	for(int i = 1; i <= n; ++i) {
	    for(int j = 1; j <= n; ++j)
			if (i != j) {
		    	if(f[j][i] > f[disnd[i]][i]){
		    		disnd2[i] = disnd[i];
		    		disnd[i] = j;
		    	}
		    	else if(f[j][i] > f[disnd2[i]][i])
		    			 disnd2[i] = j;
		    }
	}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
	    	if(i != j) {
		    	if(!disnd[i] || !disst[j] || disnd[i] == j || disst[j] == i) continue;
		  	  	if(disnd[i] == disst[j]) {
		  	  	  	if(f[disnd2[i]][i] + f[j][disst[j]] + f[i][j] > maxs && disnd2[i]) {
		  	  	  	 	maxs = f[disnd2[i]][i] + f[j][disst[j]] + f[i][j];
		  	  	  	  	ans[0] = disnd2[i]; ans[1] = i;
		  	  	  	  	ans[2] = j; ans[3] = disst[j];
		  	  	 	}
		  		  	if(f[disnd[i]][i] + f[j][disst2[j]] + f[i][j] > maxs && disst2[j]) {
		  	  	  	  	maxs = f[disnd[i]][i] + f[j][disst2[j]] + f[i][j];
		  	  	  	  	ans[0] = disnd[i]; ans[1] = i;
		  	  	  	  	ans[2] = j; ans[3] = disst2[j];
		  	  		}
		  	  	}
		  	  	else
		  	    	if(f[disnd[i]][i] + f[j][disst[j]] + f[i][j] > maxs) {
		  	  	  	  	maxs = f[disnd[i]][i] + f[j][disst[j]] + f[i][j];
		  	  	  	  	ans[0] = disnd[i];
						ans[1] = i;
		  	  	  	  	ans[2] = j; ans[3] = disst[j];
		  	  		}
		  	}
	return printf("%d %d %d %d\n", ans[0], ans[1], ans[2], ans[3]) & 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值