標籤:style blog http color 使用 os io 資料
題目連結:http://poj.org/problem?id=1724
題目意思:給出一個含有N個點(編號從1~N)、R條邊的有向圖。Bob 有 K 那麼多的金錢,需要找一條從頂點1到頂點N的路徑(每條邊需要一定的花費),前提是這個總花費 <= K.
首先這裡很感謝 yunyouxi0 ,也就是我們的ACM隊長啦~~~,他一下子指出了我的錯誤——儲存重邊的錯誤。這條題卑鄙的地方是,有重邊,discuss 中的資料過了也不一定會AC啦。大家不妨試試這組資料(隊長深情奉獻^_^)
2
2
2
1 2 2 3
1 2 3 2
ans: 3
用鄰接表來儲存就可以解決這個問題啦。看了差不多整天的鄰接表,終於看懂了,大感動啊^__^。對於初次使用的我(或者其他也是第一次接觸的讀者),希望這幅圖能幫大家理解理解~~~~
我用Sample 來解釋這幅圖
5671 2 2 32 4 3 33 4 2 41 3 4 14 6 2 13 5 2 05 4 3 2
建立一個鄰接表
struct adj_table // 鄰接表
{
int next, D, L, T;
}node[M];
首先這個F[i] 表示對於編號為 i 這個 點中跟它相鄰的點有多少個,也就是表頭!
那些0、3、1、...、5的意思實質就是第幾行輸入,假設是3 5 2 0, 是圖中的數字 5了,對於3這個點來說,如果還有一條從點3出發的邊,那麼下一次插入就從這個 5 開始。
可能我還是說得不清不楚啦~~~,結合這個運行結果還有上面那幅本人嘔心瀝血圖來看,是不是一下子豁然開朗呢?注意 j = 3(v = 3) 之後,下一個點是node[3].next ,也就是 0(v = 2),由於我們在插入的時候,node[3].D 已經把目標節點記錄下來了,還有長度和花費,所以不斷往返的時候,就能求出所有跟 j = 3 的所有相鄰節點了(再下一個是 node[0].next ,為-1 就停止了,代表已經到達頭結點:編號為1的點,剛好對於節點1來說, 2, 3 就是跟它鄰接的點,由於是回溯回去的,所以先輸出3, 再輸出2)
(first 點 6 結束了,因為從6出發沒有路!)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int INF = 10000000; 7 const int M = 10000 + 5; 8 const int maxn = 100 + 5; 9 struct adj_table // 鄰接表10 {11 int next, D, L, T;12 }node[M]; // 不要開小了!!!寫成maxn會runtime error13 14 int F[maxn]; // 表頭15 int vis[maxn];16 17 int K, N, R, flag, minlen;18 19 void dfs(int head, int r, int l)20 {21 if (l > minlen) // 剪枝,防止TLE的關鍵22 return;23 if (head == N && r >= 0)24 {25 flag = 1;26 minlen = min(minlen, l);27 return;28 }29 for (int i = F[head]; i != -1; i = node[i].next)30 {31 int v = node[i].D;32 if (!vis[v]&& r-node[i].T >= 0) // 未走過+費用足33 {34 vis[v] = 1;35 dfs(v, r-node[i].T, l+node[i].L); // 注意:不是r-node[v].T和l+node[v].L, 因為是指向下一個頂點, v是當前頂點36 vis[v] = 0;37 }38 }39 }40 41 int main()42 {43 while (scanf("%d%d%d", &K, &N, &R) != EOF)44 {45 int s, d, l, t;46 int count = 0;47 memset(vis, 0, sizeof(vis));48 memset(F, -1, sizeof(F));49 for (int i = 0; i < R; i++)50 {51 scanf("%d%d%d%d", &s, &d, &l, &t);52 node[count].next = F[s];53 node[count].D = d, node[count].L = l, node[count].T = t;54 F[s] = count++;55 }56 vis[1] = 1;57 minlen = INF, flag = 0;58 dfs(1, K, 0);59 printf("%d\n", !flag ? -1 : minlen);60 }61 return 0;62 }