Week8作業 C 班長競選

2021-10-05 01:47:33 字數 2147 閱讀 7646

問題描述:

大學班級選班長,n個同學均可以發表意見。若意見為a b,則表示a認為b合適。意見具有傳遞性,即a認為b合適,b認為c合適,則a也認為c合適。共m條意見,要求出最高票數和候選人名單。

準備知識:

kosaraju演算法:

1.第一遍 dfs 確定原圖的逆後序序列。

2.第二遍 dfs 在反圖中按照逆後序序列進行遍歷,每次由起點遍歷到的點即構成乙個 scc。

縮點:遍歷圖中每乙個點的鄰接點,如果兩個點不屬於同乙個ssc,向新圖中插入一條連線兩個ssc的邊(如果後續操作為dfs,可以不去重)。

思路解析:

1.縮點後,對於屬於第 i 個 scc 的點來說,答案分為兩部分:(令 scc[i] 表示第 i 個 scc 中點的個數 )當前 scc 中的點,ans += scc[i] – 1(去除自己),其它 scc 中的點sum ( scc[j] ),其中 j 可到達i。

2.最後答案一定出現在出度為 0 的 scc 中。

3.注意縮點後!將邊反向,對每個入度為 0 的點進行 dfs,計算其能到達的點的 sum(scc[j]),即可得到答案。

**實現:

#include

#include

#include

#include

#include

using

namespace std;

const

int n =

30030

;int k =1;

int n,c[n]

,dfn[n]

,vis[n]

,dcnt,scnt;

vector<

int> g1[n]

,g2[n]

;int num[n]

;//記錄每乙個scc能得到的最大票數

int sccnum[n]

;//儲存每乙個scc中的節點

vector<

int> map[n]

;//儲存縮點後新圖

int in[n]

;//記錄每個scc入度

bool vissc[n]

;int ans;

int t;

void

addg1

(int x,

int y)

;void

addg2

(int x,

int y)

;void

dfs1

(int x)

;void

dfs2

(int x)

;void

kosaraju()

;void

suodian()

for(

int i =

0;i}}

;void

getsccnum()

};void

dfs(

int u)}}

;void

solve()

}printf

("case %d: %d\n"

, k++

, sum -1)

;//多算1,要減去1

int flag =0;

for(

int i =

0; i < n;

++i)

}printf

("\n");

};intmain()

memset

(sccnum,0,

sizeof sccnum)

;while

(m--

)kosaraju()

;// for(int i = 0;i// cout;suodian()

;solve()

;// for(int i = 1;i<=scnt;i++)

//

//// cout<}

}

總結:感覺好複雜,用了kosaraju板子還是寫了好久,要理清思路再寫,剛開始地sccnum陣列用了個vector,存了每個scc點,但是根本沒必要。

C 班長競選(Week 8作業)

大學班級選班長,n 個同學均可以發表意見 若意見為 a b 則表示 a 認為 b 合適,意見具有傳遞性,即 a 認為 b 合適,b 認為 c 合適,則 a 也認為 c 合適 勤勞的 tt 收集了m條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?input 本題有多...

Week8 作業 C 班長競選

大學班級選班長,n 個同學均可以發表意見 若意見為 a b 則表示 a 認為 b 合適,意見具有傳遞性,即 a 認為 b 合適,b 認為 c 合適,則 a 也認為 c 合適 勤勞的 tt 收集了m條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?input 本題有多...

week8作業C 班長競選 kosaraju

題目 大學班級選班長,n 個同學均可以發表意見 若意見為 a b 則表示 a 認為 b 合適,意見具有傳遞性,即 a 認為 b 合適,b 認為 c 合適,則 a 也認為 c 合適 勤勞的 tt 收集了m條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?輸入 本題有多...