1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
// PA2026, @mjm, r0-tra

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
int nextInt() { int n; scanf("%d", &n); return n; }


// ======== Communication ========
void msgSend(int bitCount, int value) {
	for (int i = bitCount - 1; i >= 0; --i)
		printf("+ %d\n", (value >> i) & 1);
	fflush(stdout);
}

int msgReceive(int bitCount) {
	int res = 0;
	for (int i = 0; i < bitCount; ++i)
		printf("?\n");
	fflush(stdout);
	for (int i = 0; i < bitCount; ++i)
		res = (res << 1) + nextInt();
	return res;
}

void sendV(int v) { msgSend(11, v); }
void sendDist(int dist) { msgSend(9, dist); }
int getV() { return msgReceive(11); }
int getDist() { return msgReceive(9); }


// ======== Graph ========
const int N = 2000 + 9;
const int C = 500 + 9;
struct Edge {
	int v;
	int cost;

	bool operator<(const Edge& oth) const {
		if (cost != oth.cost)
			return cost > oth.cost;
		return v > oth.v;
	}
};

int n;
vector<Edge> graph[N];
char name[256];
int dist[N];

int main() {
	scanf("%s", name);

	// ==== Build graph ====
	n = nextInt();
	int m = nextInt();
	for (int i = 0; i < m; ++i) {
		int a = nextInt();
		int b = nextInt();
		int w = nextInt();
		graph[a].push_back({ b, w });
		graph[b].push_back({ a, w });
	}

	// ==== Dijkstra ====
	for (int i = 1; i <= n; ++i)
		dist[i] = -1;
	priority_queue<Edge> q;
	int src = 1;
	dist[src] = 0;
	for (int i = 0; i < graph[src].size(); ++i)
		q.push(graph[src][i]);
	int baseDist = 0;

	for (int step = 1; step < n; ++step) {
		while (!q.empty() && dist[q.top().v] >= 0)
			q.pop();
		int myDist = q.empty() ? C : q.top().cost - baseDist;
		sendDist(myDist);
		int othDist = getDist();
		bool iAmBetter = false;
		if (myDist < othDist)
			iAmBetter = true;
		if (myDist == othDist && name[0] == 'A')
			iAmBetter = true;
		int v;
		if (iAmBetter) {
			v = q.top().v;
			sendV(v);
			baseDist += myDist;
		} else {
			v = getV();
			baseDist += othDist;
		}
		dist[v] = baseDist;
		for (int i = 0; i < graph[v].size(); ++i)
			q.push({ graph[v][i].v, baseDist + graph[v][i].cost });
	}

	// ==== Print result ====
	if (name[0] == 'A') {
		printf("!");
		for (int i = 1; i <= n; ++i)
			printf(" %d", dist[i]);
		printf("\n");
		fflush(stdout);
	}

	return 0;
}