1. 程式人生 > >Gym 101673E Is-A? Has-A? Who Knowz-A?

Gym 101673E Is-A? Has-A? Who Knowz-A?

題目:傳送門

題意:有n個關係,有m個詢問,關係有a is  b,a has b  注意(a is b!=b is a),然後 is和has都具有傳遞性。

每次詢問問你a,b的關係是否正確

思路:根據is關係和has關係建邊,如果是is關係,那麼兩個點之間的邊都是is邊,如果是has關係,兩個點之間的路徑就會存在至少一個has,這樣用dfs或者最短路都可以解決。

附上程式碼:

#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
map<string, int>p;
typedef long long ll;
#define inf 0x3f3f3f3f
int gx[510][510];
int hh[510][510];
int cnt = 1;
void flod() {
	for (int i = 1; i < cnt; i++) {
		for (int z = 1; z < cnt; z++) {
			for (int k = 1; k < cnt; k++) {
				if (gx[z][i]<inf&&gx[i][k]<inf)
					gx[z][k] = min(gx[z][k], gx[z][i] + gx[i][k]);
				if (hh[z][i]<inf&&hh[i][k]<inf)
					hh[z][k] = min(hh[z][k],hh[z][i] + hh[i][k]);
				if (hh[z][k] < 0) hh[z][k] = -1;
			}
		}
	}
}
int main(void) {
	int n, m;
	p.clear();
	for (int i = 0; i < 510; i++) {
		for (int z = 0; z < 510; z++) {
			if (i == z) gx[i][z] = 0;
			else gx[i][z] = gx[z][i] = inf;
		}
	}
	for (int i = 0; i < 510; i++) {
		for (int z = 0; z < 510; z++) {
			if (i == z) hh[i][z] = 0;
			else hh[i][z] = hh[z][i] = inf;
		}
	}
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		string a, b, c;
		cin >> a >> b >> c;
		int x1, x2;
		if (p[a] == 0) {
			p[a] = cnt++;
		}
		if (p[c] == 0) {
			p[c] = cnt++;
		}
		x1 = p[a];
		x2 = p[c];
		if (b[0] == 'i') {
			gx[x1][x2] = 0;
			hh[x1][x2] = min(hh[x1][x2],0);//這裡是個bug
		}
		else if (b[0] == 'h') {
			hh[x1][x2] = -1;
		}
	}
	flod();
	for (int i = 0; i < m; i++) {
		string a, b, c;
		cin >> a >> b >> c;
		cout << "Query " << i + 1 << ": ";
		if (b[0] == 'i') {
			if (gx[p[a]][p[c]] == 0) {
				cout << "true" << endl;
			}
			else cout << "false" << endl;
		}
		else if (b[0] == 'h') {
			if (hh[p[a]][p[c]] < 0) {
				cout << "true" << endl;
			}
			else cout << "false" << endl;
		}
	}
	return 0;
}