2011-06-21 11:48:59Morris

b058. 3. 關鍵邏輯閘

b058. 3. 關鍵邏輯閘

內容 :

一個組合電路(combinational circuit)由線路(wires)連接一組邏輯閘(logic gates)而成,並且不包含有向迴路(directed cycle)。一個組合電路的效能決定於最後一個主要輸出(primary output)被算出來的時間。假設每一個邏輯閘所需的運算時間都是固定並且是已知的,而線路的延遲(delay)是0。我們希望把一個組合電路所有的關 鍵邏輯閘找出來。若一個邏輯閘的運算時間有任何延長,便會影響到整個電路的效能,它就被稱為關鍵邏輯閘。以圖一的組合電路為例,I1、I2、I3是主要輸入;O1、O2是主要輸出;圓圈代表邏輯閘,箭頭代表線路;每個邏輯閘有自己的編號以及固定的延遲時間。在圖一的例子當中,該組合電路中的O1會因為邏輯閘2、4、5的延遲,在時間400才會收到運算結果;而O2會因為邏輯閘2、4、6的延遲,在時間600才收到運算結果,因此O2是最後一個被算出來的主要輸出。關鍵邏輯閘分別是2、4以及6號邏輯閘,當其中一個關鍵邏輯閘的運算時間有任何延長,O2被算出來的時間也會再往後延遲。相反地,就算1號邏輯閘的運算時間從150延長到160,也不會影響到O2被算出來的時間,因此1號邏輯閘並不是關鍵邏輯閘。

輸入說明 :

第一行為一個整數 n (0 < n < 10000),代表一個組合電路的邏輯閘總數,每個邏輯閘的編號都不同,且範圍是介於 1~n 之間的整數。第二行為一個整數 m (m < 50000),代表線路的總數。接下來的 n 行,依序列出每個邏輯閘的運算時間;每個運算時間的值是介於 0 到 600 之間(含)的整數。最後 m 行,分別列出每一條線路由某個邏輯閘的輸出接到另一個邏輯閘的輸入。
注意:為簡化輸入,我們把主要輸入(primary inputs)與邏輯閘之間的線路,以及邏輯閘與主要輸出(primary outputs)之間的線路省略。(每一個邏輯閘至少都含有一個線路輸出到另一個邏輯閘或主要輸出)

 

輸出說明 :

列出關鍵邏輯閘的個數。

範例輸入 :

6
6
150 
200 
150 
100 
100 
300 
1 5 
1 4 
2 4 
4 5 
4 6 
3 6 
5
4
200
200
400
250
200
1 2
3 2
3 5
4 5

範例輸出 :

3
3

提示 :

出處 :

95全國資訊學科能力決賽



作法 : DP
題目主要是在講說
由輸入到輸出時間消耗最久的路徑,路徑可能不只有一條,將會出現在最久路徑上的點個數輸出
需要用DP & 回朔找點個數

/**********************************************************************************/
/*  Problem: b058 "3. 關鍵邏輯閘" from 95全國資訊學科能力決賽      */
/*  Language: C                                                                   */
/*  Result: AC (10ms, 522KB) on ZeroJudge                                         */
/*  Author: morris1028 at 2011-06-19 23:12:54                                     */
/**********************************************************************************/


#include<stdio.h>
typedef struct {
    int x, y;
}Link;
Link Next[50001], Pre[50001], X[50001];
int A[10001], DP[10001];
int Sn[10001], Cn[10001], pres[10001], prec[10001];
void MergeSort(int , int, Link[]);
void Merge(int , int , int, Link[]);
int Backtracking(int n) {
    int a, b, c, tn, Max = -1;
    int Queue[10001], Qt = -1, Used[10001] = {};
    for(a = 1; a <= n; a++)
        Max = (Max > DP[a]) ? Max : DP[a];
    for(a = 1; a <= n; a++)
        if(DP[a] == Max)
            Queue[++Qt] = a, Used[a] = 1;
    for(a = 0; a <= Qt; a++) {
        tn = Queue[a];
        for(b = 0, c = pres[tn]; b < prec[tn]; b++, c++)
            if(DP[tn] == A[tn] + DP[Pre[c].y]) {
                if(Used[Pre[c].y] == 0) {
                    Used[Pre[c].y] = 1;
                    Queue[++Qt] = Pre[c].y;
                }
            }
    }
    return Qt+1;
}
int    BFS_DP(int n) {
    int a, b, c, tn;
    int Queue[20001], Qt = -1, Used[10001] = {};
    for(a = 1; a <= n; a++) {
        DP[a] = -1;
        if(prec[a] == 0)
            Queue[++Qt] = a, Used[a] = 1, DP[a] = A[a];
    }
    for(a = 0; a <= Qt; a++) {
        tn = Queue[a];
        for(b = 0, c = Sn[tn]; b < Cn[tn]; b++, c++)
            if(DP[Next[c].y] < A[Next[c].y] + DP[tn]) {
                DP[Next[c].y] = A[Next[c].y] + DP[tn];
                if(Used[Next[c].y] == 0) {
                    Used[Next[c].y] = 1;
                    Queue[++Qt] = Next[c].y;
                }
            }
        Used[tn] = 0;
    }
    return Backtracking(n);
}
main() {
    int n, m, a, C = 0;
    while(scanf("%d %d", &n, &m) == 2) {
        for(a = 1; a <= n; a++)
            scanf("%d", &A[a]);
        for(a = 0; a < m; a++) {
            scanf("%d %d", &Next[a].x, &Next[a].y);
            Pre[a].x = Next[a].y;
            Pre[a].y = Next[a].x;
        }
        for(a = 1; a <= n; a++)
            Sn[a] = -1, Cn[a] = 0, pres[a] = -1, prec[a] = 0;
        MergeSort(0, m-1, Next);
        MergeSort(0, m-1, Pre);
        for(a = 0; a < m; a++) {
            if(Sn[Next[a].x] == -1)
                Sn[Next[a].x] = a;
            Cn[Next[a].x] ++;
        }
        for(a = 0; a < m; a++) {
            if(pres[Pre[a].x] == -1)
                pres[Pre[a].x] = a;
            prec[Pre[a].x] ++;
        }
        printf("%d\n", BFS_DP(n));
    }
    return 0;
}
void Merge(int l, int m, int h, Link Data[]) {
    int In1 = l, In2 = m+1;
    int a, b, Top = 0;
    while(In1 <= m && In2 <= h)
        if(Data[In1].x < Data[In2].x)
            X[Top++] = Data[In1++];
        else X[Top++] = Data[In2++];
    while(In1 <= m)    X[Top++] = Data[In1++];
    while(In2 <= h) X[Top++] = Data[In2++];
    
    for(a = 0, b = l; a < Top; a++, b++)
        Data[b] = X[a];
}
void MergeSort(int l, int h, Link Data[]) {
    if(l < h) {
        int m = (l+h)/2;
        MergeSort(l, m, Data);
        MergeSort(m+1, h, Data);
        Merge(l, m, h, Data);
    }
}