題目:
一個旅遊景點,如果被帶火了的話,就被稱為“網紅點”。大家來網紅點遊玩,俗稱“打卡”。在各個網紅點打卡的快(省)樂(錢)方法稱為“攻略”。你的任務就是從一大堆攻略中,找出那個能在每個網紅點打卡僅一次、並且路上花費最少的攻略。
輸入格式:
首先第一行給出兩個正整數:網紅點的個數 N(1<N≤200)和網紅點之間通路的條數 M。隨後 M 行,每行給出有通路的兩個網紅點、以及這條路上的旅行花費(為正整數),格式為“網紅點1 網紅點2 費用”,其中網紅點從 1 到 N 編號;同時也給出你家到某些網紅點的花費,格式相同,其中你家的編號固定為 0。
再下一行給出一個正整數 K,是待檢驗的攻略的數量。隨後 K 行,每行給出一條待檢攻略,格式為:n V1 V2 ⋯ Vn
其中 n(≤200) 是攻略中的網紅點數,Vi是路徑上的網紅點編號。這裡假設你從家裡出發,從V1開始打卡,最後從 Vn回家。
輸出格式:
在第一行輸出滿足要求的攻略的個數。
在第二行中,首先輸出那個能在每個網紅點打卡僅一次、並且路上花費最少的攻略的序號(從 1 開始),然後輸出這個攻略的總路費,其間以一個空格分隔。如果這樣的攻略不唯一,則輸出序號最小的那個。
題目保證至少存在一個有效攻略,並且總路費不超過 1e9.
輸入樣例:
6 13
0 5 2
6 2 2
6 0 1
3 4 2
1 5 2
2 5 1
3 1 1
4 1 2
1 6 1
6 3 2
1 2 1
4 5 3
2 0 2
7
6 5 1 4 3 6 2
6 5 2 1 6 3 4
8 6 2 1 6 3 4 5 2
3 2 1 5
6 6 1 3 4 5 2
7 6 2 1 3 4 5 2
6 5 2 1 4 3 6
輸出樣例:
3
5 11
樣例說明:
第 2、3、4、6 條都不滿足攻略的基本要求,即不能做到從家裡出發,在每個網紅點打卡僅一次,且能回到家裡。所以滿足條件的攻略有 3 條。
第 1 條攻略的總路費是:(0->5) 2 + (5->1) 2 + (1->4) 2 + (4->3) 2 + (3->6) 2 + (6->2) 2 + (2->0) 2 = 14;
第 5 條攻略的總路費同理可算得:1 + 1 + 1 + 2 + 3 + 1 + 2 = 11,是一條更省錢的攻略;
第 7 條攻略的總路費同理可算得:2 + 1 + 1 + 2 + 2 + 2 + 1 = 11,與第 5 條花費相同,但序號較大,所以不輸出。
打比賽的時候,疑惑為什麼樣例說明第3條不滿足。卡在了閱讀理解上了。
題解:給你k個攻略,每個攻略要求你檢查可行性。如果可行(題目保證一定有可行的),再求攻略的最少花費,如果有相同的最少花費攻略,優先輸出序號最小的。第一行輸出可行的攻略數量,第二行輸出最少花費的最小ID和最少花費。
建議用鄰接矩陣建圖。
可行性:
1、n個點都要訪問且只訪問一次(用一個vis陣列記錄一下輸入的攻略路線:vis[v[i]]++,檢查一下vis[1~n],要求都是1)。2、要求從0出發經過攻略路線再到0要有邊連線(在檢查的過程中計算花費)。
最少花費ID和最少花費:在可行性的基礎上選擇一下就好。
補題程式碼:
#include<bits/stdc++.h> using namespace std; #define ll long long const int N = 200+5; #define inf 0x3f3f3f3f #define mod 998244353 #define pre(a,b,c) for(int a=b;a<c;a++) #define pres(a,b,c) for(int a=b;a<=c;a++) int G[N][N]; int a[N],sum,q,vis[N],n,m; bool BFS(int s) { for(int j = 1;j <= n;j++) { if(vis[j]!=1) { return false; } } sum = 0; for(int i = 0;i < q;i++) { if(G[s][a[i]]==inf) { return false; } sum += G[s][a[i]]; s = a[i]; } if(G[s][0]==inf) { return false; } sum += G[s][0]; return true; } int main() { cin>>n>>m; memset(G,inf,sizeof G); for(int i = 0,u,v,w;i < m;i++) { cin>>u>>v>>w; G[u][v] = G[v][u] = w; } int mi = inf,k,id,cnt = 0; cin>>k; for(int i = 0;i < k;i++) { cin>>q; memset(vis,0,sizeof vis); for(int j = 0;j < q;j++) { cin>>a[j]; vis[a[j]]++; } if(BFS(0)) { if(mi > sum) { id = i+1; mi = sum; } cnt++; } } cout<<cnt<<endl; cout<<id<<' '<<mi<<endl; }