// David Poeschl import java.util.*; public class TranslationDavid { private static Language[] targetLanguages; private static HashMap languageNameToLanguage; public static void main(String[] args) { readInputAndCreateDataStructures(); calculateLengthOptimizedMST(); // Make sure all target languages were reachable for (Language language : targetLanguages) { if (!language.seen) { System.out.println("Impossible"); return; } } int totalCost = 0; for (Translator t : calculateNecessaryTranslators()) totalCost += t.cost; System.out.println(totalCost); } private static void readInputAndCreateDataStructures() { Scanner scan = new Scanner(System.in); int numTargetLanguages = scan.nextInt(); int numTranslators = scan.nextInt(); languageNameToLanguage = new HashMap(); languageNameToLanguage.put("English", Language.createEnglish()); targetLanguages = new Language[numTargetLanguages]; for (int i = 0; i < numTargetLanguages; i++) { String languageName = scan.next(); languageNameToLanguage.put(languageName, new Language(languageName)); targetLanguages[i] = languageNameToLanguage.get(languageName); } for (int i = 0; i < numTranslators; i++) { String lang1Name = scan.next(); if (!languageNameToLanguage.containsKey(lang1Name)) languageNameToLanguage.put(lang1Name, new Language(lang1Name)); String lang2Name = scan.next(); if (!languageNameToLanguage.containsKey(lang2Name)) languageNameToLanguage.put(lang2Name, new Language(lang2Name)); Translator t = new Translator(languageNameToLanguage.get(lang1Name), languageNameToLanguage.get(lang2Name), scan.nextInt()); t.lang1.translators.add(t); t.lang2.translators.add(t); } scan.close(); } private static void calculateLengthOptimizedMST() { Set languagesAtCurrentDistance = new HashSet(); languagesAtCurrentDistance.add(languageNameToLanguage.get("English")); while (languagesAtCurrentDistance.size() > 0) { HashMap newlyReachableLanguages = new HashMap(); for (Language language : languagesAtCurrentDistance) { for (Translator translator : language.translators) { Language possibleLanguage = translator.getOtherLanguage(language); if (possibleLanguage.seen) continue; else if (!newlyReachableLanguages.containsKey(possibleLanguage) || translator.cost < newlyReachableLanguages.get(possibleLanguage).cost) newlyReachableLanguages.put(possibleLanguage, translator); } } for (Language newLanguage : newlyReachableLanguages.keySet()) { newLanguage.seen = true; newLanguage.translatorToThisLanguage = newlyReachableLanguages.get(newLanguage); } languagesAtCurrentDistance = newlyReachableLanguages.keySet(); } } // Not all translators used in the MST are necessary (e.g. when they lead to a non-target language // which doesn't then lead back to a target language). private static HashSet calculateNecessaryTranslators() { HashSet translatorsUsed = new HashSet(); for (Language language : targetLanguages) { Translator translator = language.translatorToThisLanguage; while(translator != null && !translatorsUsed.contains(translator)) { translatorsUsed.add(translator); language = translator.getOtherLanguage(language); translator = language.translatorToThisLanguage; } } return translatorsUsed; } private static class Language { public boolean seen; public String name; public List translators = new ArrayList(); public Translator translatorToThisLanguage; public Language(String name) { this.name = name; } public static Language createEnglish() { Language lang = new Language("English"); lang.seen = true; return lang; } } private static class Translator { public Language lang1; public Language lang2; public int cost; public Translator(Language lang1, Language lang2, int cost) { this.lang1 = lang1; this.lang2 = lang2; this.cost = cost; } public Language getOtherLanguage(Language lang) { return lang.name == lang1.name ? lang2 : lang1; } } }