大學班級選班長,n 個同學均可以發表意見
若意見為 a b 則表示 a 認為 b 合適,意見具有傳遞性,即 a 認為 b 合適,b 認為 c 合適,則 a 也認為 c 合適
勤勞的 tt 收集了m條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?
輸入格式:
本題有多組資料。第一行 t 表示資料組數。每組資料開始有兩個整數 n 和 m (2 <= n <= 5000, 0 輸出格式:
對於每組資料,第一行輸出 「case x: 」,x 表示資料的編號,從1開始,緊跟著是最高的票數。
接下來一行輸出得票最多的同學的編號,用空格隔開,不忽略行末空格!
樣例輸入:
2樣例輸出:4 33 2
2 02 1
3 31 0
2 10 2
case 1: 2題目分析:0 1case 2: 2
0 1 2
能夠想到將同乙個連通分量中的點聚集,要計算得票數包括本連通分量中的點及只想該連通分量的其他連通分量中的值。
所以遮體的關鍵:1)找到圖中所有的scc
2)縮點,確定每個scc的指向關係
演算法實現:
1)用kosaraju求scc
第一遍dfs遍歷原圖,確定原圖的後序序列
將後序序列變成逆後序序列,第二遍dfs按照逆後序序列遍歷反圖,確定所有scc,遍歷過程中記錄每個scc中點的數目。
2)縮點
將同乙個scc的點合併成乙個點,遍歷反圖中的每個點的邊,如果邊的兩端不在同一scc中則加入該邊,最終形成新的縮點後的圖。
3)計算票數:
遍歷縮點後的圖,對於入度為0的點(反圖,實際上指向它,即可以給它投票),dfs計算該點總共獲得的票數(減去自身)
#include
#include
using
namespace std;
int t,m,n,a,b,tot1,tot2,tot3,dcnt,scnt,r,themax;
struct edge
; edge e1[
30010
],e2[
30010
],e3[
30010];
int head1[
5010
],head2[
5010
],head3[
5010];
int vis[
5010
],vis2[
5010
],d[
5010
],c[
5010];
//d記錄後序序列,c記錄所在scc編號
int sz[
5010
],indegree[
5010
],res[
5010];
//記錄每個scc中的點的個數 ,每個scc的入度
void
add1
(int a,
int b)
void
add2
(int a,
int b)
void
add3
(int a,
int b)
void
init()
tot1=
0;tot2=
0;tot3=
0;dcnt=
0;scnt=0;
}void
dfs1
(int x)
d[++dcnt]
=x;}
void
dfs2
(int x)
}void
dfs3
(int x)
void
kosaraju()
}void
shrink()
}}intmain()
kosaraju()
;shrink()
;for
(int j=
1;j<=scnt;j++)}
themax=0;
for(
int j=
1;j<=scnt;j++)if
(themax) themax=res[j]
;//確定最大值
printf
("case %d: %d\n"
,i+1
,themax)
;int t_num=0;
for(
int j=
0;j)else
printf
(" %d"
,j);}}
printf
("\n");
}return0;
}
班長競選(kosaraju縮點
大學班級選班長,n 個同學均可以發表意見 若意見為 a b 則表示 a 認為 b 合適,意見具有傳遞性,即 a 認為 b 合適,b 認為 c 合適,則 a 也認為 c 合適 勤勞的 tt 收集了m條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?本題有多組資料。第一...
Tarjan求連通分量 縮點
1.強連通 在乙個圖中對於任意兩個點都可以互相到達那麼就稱這個圖為強連通圖。連通分量 乙個圖的極大強連通子圖,稱為強連通分量 乙個連通分量比較類似於乙個集合,裡面的任點都可以互相到達 縮點 把乙個連通分量整體看作是乙個節點,那麼這個節點就是縮點 2.tarjan演算法 考慮維護三個陣列 vis,df...
演算法 強連通分量縮點
有時對於乙個有向圖我們及其渴望將其變為乙個有向無環圖,這樣我們就要用到強連通分量縮點了。洛谷3387 縮點 題目背景 縮點 dp。題目描述 給定乙個 n個點 m條邊有向圖,每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。允許多次經過一條邊或者乙個點,但是,重複經過的...