日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

poj1236-Tarjan算法

發布時間:2025/3/13 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj1236-Tarjan算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目大意:
一些學校連成了網絡, 在學校之間存在某個協議:每個學校都維護一張傳送表,表明他們要負責將收到的軟件傳送到表中的所有學校。如果A在B的表中,那么B不一定在A的表中。
現在的任務就是,給出所有學校及他們維護的表,問1、如果所有學校都要被傳送到,那么需要幾份軟件備份;2、如果只用一份軟件備份,那么需要添加幾條邊?
題解:
1.即求強聯通分量的個數,或者說是縮點以后入度為0的個數。
2.所有學校都連成一個強聯通分量,只需要將圖中的強聯通分量互相之間聯通就好了。添加的邊數就是縮點后入度為0的點和出度為0的點的最大值

#include <stdio.h> #include <string.h> #include <queue> using namespace std;#define MAXN 110 #define INF 0x3f3f3f3f int n; int map[MAXN][MAXN]; int low[MAXN]; int dfn[MAXN]; int stack[MAXN], head; int instack[MAXN]; int belong[MAXN]; int in[MAXN]; int out[MAXN]; int index, cnt;int min(int a, int b) {return a < b ? a : b; }int max(int a, int b) {return a > b ? a : b; }void init() {int i, j;int temp;memset(map, 0, sizeof(map));memset(dfn, -1, sizeof(dfn));memset(low, 0, sizeof(low));memset(instack, 0, sizeof(instack));index = cnt = 1;head = 0;for(i= 1; i <= n; i++){while(scanf("%d", &temp) && temp){map[i][temp] = 1;}} } void tarjan(int x) {int i, a;low[x] = dfn[x] = index; // 剛搜到一個節點時low = dfnindex++;stack[++head] = x; // 將該節點入棧 instack[x] = 1; // 將入棧標記設置為1for(i = 1; i <= n; i++) // 遍歷入棧節點的邊{if(!map[x][i]) // 如果兩點之間沒有邊continue; // 不用管它if(dfn[i] == -1) // 如果新搜索到的節點是從未被搜索過{tarjan(i); // 那自然就得搜索這個節點low[x] = min(low[x], low[i]); // 回溯的時候改變當前節點的low值 }else if(instack[i]) // 如果新搜索到的節點已經被搜索過而且現在在棧中 {low[x] = min(low[x], dfn[i]); // 更新當前節點的low值,這里的意思是兩個節點之間有一條可達邊,而前面 } // 而前面節點已經在棧中,那么后面的節點就可能和前面的節點在一個聯通分量中 } if(low[x] == dfn[x]) // 最終退回來的時候 low == dfn , 沒有節點能將根節點更新,那 { // low == dfn 的節點必然就是根節點int temp; while(1) // 一直出棧到此節點, 這些元素是一個強聯通分量 {temp = stack[head--]; // 彈出棧元素 belong[temp] = cnt; // 為了方便計算,將強聯通分量進行標記instack[temp] = 0; // 將棧內標記置為0 if(temp == x) // 一直彈到x出現為止 break;}cnt++;} } void solve() {int i, j;int t1, t2;while(scanf("%d", &n) != EOF) //{init(); // 初始化 for(i = 1; i <= n; i++) // if(dfn[i] == -1) // 如果某點沒被訪問過,則對其進行tarjan tarjan(i); // tarjan的成果是得到了一個belong數組,記錄每個節點分別屬于哪個強聯通分量 **for(i = 1; i <= n; i++) // 遍歷每條邊,找到縮點之后的邊 {for(j = 1;j <= n; j++){if(map[i][j] && belong[i] != belong[j]) // 兩點之間有邊,但不是屬于一個強聯通分量的邊{out[belong[i]]++; // 縮點后的點入度+1 in[belong[j]]++;// 縮點后的點出度+1 } } }** //縮點t1 = 0, t2 = 0;for(i = 1; i < cnt; i++){if(in[i] == 0)t1++;if(out[i] == 0)t2++;}if(cnt == 2)printf("1\n0\n");elseprintf("%d\n%d\n", t1, max(t1, t2));//縮點后入度為0的點和出度為0的點的最大值} }int main() { #ifdef LOCALfreopen("poj1236.txt", "r", stdin);// freopen(".txt", "w", stdout); #endifsolve();return 0; }

轉載于:https://www.cnblogs.com/luckycode/p/5255650.html

總結

以上是生活随笔為你收集整理的poj1236-Tarjan算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。