#include "bits/stdc++.h" using namespace std; //現在と次の頂点のboolean bool now[2000]; bool nextt[2000]; int main(){ //n=town, //m=load//k回分の料金 int N, M, K; cin >> N >> M >> K; //a,b,c=a街,b街,kの配列 vector a(M), b(M), c(M); for (int i = 0; i < M; i++) { cin >> a[i] >> b[i] >> c[i]; //a=1引いておくと後で計算楽になる。 a[i]--; b[i]--; } //料金がdであとで比較のために作る。 vector d(K); for (int i = 0; i < K; i++) { cin >> d[i]; } for (int i = 0; i < N; i++) { //現在の道の状況をtrueであとで再帰的にtrueのやつをカウントしておく。 now[i] = true; nextt[i] = false; } //全文探索はfor文重ねて、if_continueで枝切りで行ける。 //料金所*道の数だけループ回す。 for (int i = 0; i < K; i++) { //道の数 for (int j = 0; j < M; j++) {//counterが違うものであれば、続ける。 if (c[j] != d[i]) continue; //a街とb街をtureにする。両方とも //前からのものがtrueで料金所の街なら、次の街もtrueになる nextt[a[j]] |= now[b[j]]; nextt[b[j]] |= now[a[j]]; } //ここの行がポイントで、最初の料金所に引っかからなかった街Nはここでnexttがないので振り落とされる。 //つまり、nexttはデフォルトがfalseなので、それに引っかからないbooleanはこの段階で落としてしまう。 for (int j = 0; j < N; j++) { //1からNまで振られている。jは街の数で何もtrueがなければそこで終わりになる。 //ここでどんどん枝刈りでふるいに落とされる。2つ枝刈り。booleanで now[j] = nextt[j]; nextt[j] = false; } } int count = 0; //最後にnowcountがtrueのものが可能性のある街になる。 for (int i = 0; i < N; i++) { if (now[i]){ count++; } } cout << count << endl; //N以上ないから、そこで虱潰しにtrueのみ、出力する。 for (int i = 0; i < N; i++) { if (now[i]){ //マイナスでなければ、街の数を出して、スペース。マイナスは最終行を意味するので、そこではendlで対処 if (--count) cout << (i + 1) << " "; else cout << (i + 1) << endl; } } }