問題描述:
大學班級選班長,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條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?輸入 本題有多...