時間限制: 3 sec
記憶體限制: 64 mb
提交: 4
解決: 4
南陽理工學院共有m個系,分別編號1~m,其中各個系之間達成有一定的協議,如果某系有新軟體可用時,該系將允許一些其它的系複製並使用該軟體。但該允許關係是單向的,即:a系允許b系使用a的軟體時,b未必一定允許a使用b的軟體。
現在,請你寫乙個程式,根據各個系之間達成的協議情況,計算出最少需要新增多少個兩系之間的這種允許關係,才能使任何乙個系有軟體使用的時候,其它所有系也都有軟體可用。
第一行輸入乙個整數t,表示測試資料的組數(t<10) 每組測試資料的第一行是乙個整數m,表示共有m個系(2<=m<=100)。 隨後的m行,每行都有一些整數,其中的第i行表示系i允許這幾個系複製並使用系i的軟體。每行結尾都是乙個0,表示本行輸入結束。如果某個系不允許其它任何系使用該系軟體,則本行只有乙個0.
對於每組測試資料,輸出最少需要新增的這種允許關係的個數。
152 4 3 0
4 5 000
1 0
2nyoj120
nyoj圖論
**
tarjan演算法詳解
【功能】
tarjan演算法的用途之一是,求乙個有向圖g=(v,e)裡極大強連通分量。強連通分量是指有向圖g裡頂點間能互相到達的子圖。而如果乙個強連通分量已經沒有被其它強通分量完全包含的話,那麼這個強連通分量就是極大強連通分量。
【演算法思想】
用dfs遍歷g中的每個頂點,通dfn[i]表示dfs時達到頂點i的時間,low[i]表示i所能直接或間接達到時間最小的頂點。(實際操作中low[i]不一定最小,但不會影響程式的最終結果)
程式開始時,order初始化為0,在dfs遍歷到v時,low[v]=dfn[v]=order++,
v入棧(這裡的棧不是dfs的遞迴時系統弄出來的棧)掃瞄一遍v所能直接達到的頂點k,如果 k沒有被訪問過那麼先dfs遍歷k,low[v]=min(low[v],low[k]);如果k在棧裡,那麼low[v]=min(low[v],dfn[k])(就是這裡使得low[v]不一定最小,但不會影響到這裡的low[v]會小於dfn[v])。掃瞄完所有的k以後,如果low[v]=dfn[v]時,棧裡v以及v以上的頂點全部出棧,且剛剛出棧的就是乙個極大強連通分量。
【大概的證明】
1. 在棧裡,當dfs遍歷到v,而且已經遍歷完v所能直接到達的頂點時,low[v]=dfn[v]時,v一定能到達棧裡v上面的頂點:
因為當dfs遍歷到v,而且已經dfs遞迴呼叫完v所能直接到達的頂點時(假設上面沒有low=dfn),這時如果發現low[v]=dfn[v],棧上面的頂點一定是剛才從頂點v遞迴呼叫時進棧的,所以v一定能夠到達那些頂點。
2 .dfs遍歷時,如果已經遍歷完v所能直接到達的頂點而low[v]=dfn[v],我們知道v一定能到達棧裡v上面的頂點,這些頂點的low一定小於 自己的dfn,不然就會出棧了,也不會小於dfn[v],不然low [v]一定小於dfn[v],所以棧裡v以其v以上的頂點組成的子圖是乙個強連通分量,如果它不是極大強連通分量的話low[v]也一定小於dfn[v](這裡不再詳細說),所以棧裡v以其v以上的頂點組成的子圖是乙個極大強連通分量。
【時間複雜度】
因為所有的點都剛好進過一次棧,所有的邊都訪問的過一次,所以時間複雜度為o(n+m)
// 強連通分量縮點
#include #include #include #include using namespace std;
const int max = 105;
int map[max][max];//用鄰接矩陣記錄圖
int low[max];//記錄的是節點所能找到的最先進入棧的節點的次序
int dfn[max];//記錄節點被搜尋的次序
int in[max];//統計縮點(由乙個強連通分量內的所有點所組成的集合稱為縮點)的入度
int out[max];//統計縮點(由乙個強連通分量內的所有點所組成的集合稱為縮點)的出度
int instack[max];//標記節點是否在棧中??????
int t[max];//作用?????
int n, order, res, ans;
stacks;
void init()//初始化陣列
int min(int x, int y)//找最小值
void tr(int u)
else if(instack[i])//否則如果相鄰節點已經在棧中 更新low[u](能找到的最先進入棧的節點的次序),取得是low[u]與dfn[i]的最小值
low[u] = min(low[u], dfn[i]);}}
if(dfn[u] == low[u])//如果該點的dfn值與low值相同,則說明該點是某強連通分量的第乙個點
//(因為乙個強聯通圖中有且僅有乙個節點的dfn值與low值相同,該點即是第乙個被搜尋到的點)
while(v != u);//將u之後的節點全部彈出棧,他們將構成乙個強連通分量(根據棧的特性,第乙個被訪問的節點一定在棧底)
}}void tarjan()//
void solve()
}int xx, yy;
xx = yy = 0;
for(int i = 1; i <= res; i++)
ans = xx > yy ? xx : yy; // 結果為縮點後的有向圖中出度為0或者入度為0中的大者
}int main()
tarjan();
solve();
if(res == 1)
printf("0\n");
else
printf("%d\n", ans);
}return 0;
}
校園網路(模擬)
校園網路 時間限制 3000 ms 記憶體限制 65535 kb 難度 5 描述 南陽理工學院共有m個系,分別編號1 m,其中各個系之間達成有一定的協議,如果某系有新軟體可用時,該系將允許一些其它的系複製並使用該軟體。但該允許關係是單向的,即 a系允許b系使用a的軟體時,b未必一定允許a使用b的軟體...
校園網路(模擬)
校園網路 時間限制 3000 ms 記憶體限制 65535 kb 難度 5 描述南陽理工學院共有m個系,分別編號1 m,其中各個系之間達成有一定的協議,如果某系有新軟體可用時,該系將允許一些其它的系複製並使用該軟體。但該允許關係是單向的,即 a系允許b系使用a的軟體時,b未必一定允許a使用b的軟體。...
NYOJ 120 校園網路
時間限制 3000 ms 記憶體限制 65535 kb 難度 5 描述 南陽理工學院共有m個系,分別編號1 m,其中各個系之間達成有一定的協議,如果某系有新軟體可用時,該系將允許一些其它的系複製並使用該軟體。但該允許關係是單向的,即 a系允許b系使用a的軟體時,b未必一定允許a使用b的軟體。現在,請...