Codeforces Round #581 (Div. 2) C. Anna, Svyatoslav and Maps (floyd)

题目链接:https://codeforces.com/contest/1204/problem/C

思路:先用floyd求出任意两点间最短路,然后逐一对每个点进行判断,设上一个必须出现在子序列中的点为cnt,若满足g[ cnt ] [ p[i+1] ] < g[ cnt ] [ p[i] ] + g[ p [ i ] ] [ p [ i + 1 ] ] , 说明从cnt到p[i+1]按最短路走不经过p[i], 所以p[i]必须出现。然后把p[i]加入序列,即
cnt = p[i] .

代码:

#include 

using namespace std;

const int maxn = 205;

const int INF = 0x7f7f7f7f;
const int N = 1e6 + 5;


int g[maxn][maxn];
int p[N];
bool f[N];


int main() {
	int n , m;
	ios::sync_with_stdio(0);
	cin >> n;
	for(int i = 1 ;i <= n ; i++) {
		for(int j = 1 ; j <= n ; j++) {
			char t;
			cin >> t;
			g[i][j] = t - '0';
			if(!g[i][j])g[i][j] = INF;
		}
	}
	for(int k = 1 ; k <= n ; k++) {
		for(int i = 1 ; i <= n ; i++) {
			for(int j = 1 ; j <= n ; j++) {
				if(g[i][k] < INF && g[k][j] < INF)
				g[i][j] = min(g[i][k] + g[k][j] , g[i][j]);
			}
		}
	}
 	
	cin >> m;
	int t = m;
	for(int i = 1 ; i <= m ; i++)cin >> p[i];
	int cnt = p[1];
	for(int i = 2 ; i <= m - 1 ; i++) {
		if(g[cnt][p[i]] + g[p[i]][p[i + 1]] <= g[cnt][p[i + 1]] && cnt != p[i+1]) {
			f[i] = 1;
			t--;
		}
		else cnt = p[i];
	}
	cout << t << "\n";
	for(int i = 1 ; i <= m ; i++) {
		if(f[i])continue;
		cout << p[i] << " ";
	}
}

你可能感兴趣的:(codeforces,最短路)