單身三連之三

2022-05-06 20:57:07 字數 1952 閱讀 5873

這是最終章,永久的思念。

題目大意:

有n張牌,每張牌兩面都有數字,範圍都在1到2n之間,求最少的反轉次數,使得每張牌朝上的一面的數字各不相同,並求出達到這個效果的方案數。(多測,初始時每張牌正面朝上,無解輸出「-1 -1」)

題解:20%資料(n<=20)

直接搜尋即可。

100%資料(n<=1×105)

搜尋複雜度不允許,我們試圖讓這個問題抽象化。

將牌上的數字抽象為點,牌抽象為邊,則問題轉化為:

對於一張有向圖,將某些邊翻轉,使得每個點的入度小於等於1。

先連邊,我們發現整張圖最多有2n個點,卻只有n條邊。這代表圖的連通性極差,圖被分成許多聯通塊,然後我們對於每個聯通塊進行分類討論。

設連通塊的邊數為e,點數為v。

若e若e=v,則該圖是一顆基環樹,環上的點入度不能為0,因為環上的點一定會被另乙個環上的點指向,要使條件成立,則一定是一顆基還外向樹;

若e=v+1,則該圖是一棵樹,可以先後進行兩次dfs,求出所需要的最小花費。

第一次任選一點進行dfs,由兒子向父親更新,若通過一條反邊,則在f陣列上加1,若dfs的是一顆基環樹,則還需要記錄未經過的一條邊,防止第二次dfs的路徑與第一次不同。然後進行第二次,由父親向兒子更新,若通過反邊,則在g陣列上加1,反之減1。g陣列與f陣列在搜尋樹的根處相等。

在進行第二次dfs時,將每個節點的g值壓進乙個vector裡面,然後sort一下,第乙個便是最小值,與最小值相同的數的個數便是方案數。

最後相乘即可。

單次複雜度o(nlogn)

code:

1 #include2 #include3 #include4 #include5 #include6

#define ll long long

7using

namespace

std;

8const

int n=100010;9

const ll mod=998244353;10

int t,n,m=1,mv=0,me=0,cnt=0,tot=0,top=0

,start,endd,bridge;

11int fi[n<<1],g[n<<1],f[n<<1

];12

bool v[n<<1],vis[n<<1

];13

struct

edgee[n<<1

];16 vectorgg;

17void add(int x,int

y)18

24int

read()

2533

return

s;34}35

void

clean()

3645

void dfs(int

x)4654}

55void dfs1(int x,int

p)56

64else68}

69}70void dfs2(int x,int

p)7179}

80int

main()

8191

int flag=0;92

for(int i=1;i<=2*n;i++)

100}

101}

102if(flag==1) continue

;103

int ans1=0;ll ans2=1

;104

for(int i=1;i<=2*n;i++)

118}

119else

125 ans2=ans2*num%mod;

126}

127}

128 printf("

%d %lld\n

",ans1,ans2);

129}

130return0;

131 }

view code

單身三連之一

乙個讓單身狗們崩潰的題 題目大意 有n件物品,一共取d次,一次取的必須少於m件,問共有多少種取法。每個物品相同,有多測,對998244353取模 題解 30 演算法 n,d 20,m 10 簡單的dp。設f i j 為取了i次,共取了j件物品的方案數,則有如下狀態轉移方程 f i j kk max ...

NOIP三連測總結

近三天舉行了三場考試,好像考得都不咋地,與上一周專題訓練相比相差甚遠。單就分數來說,基本看不下去。基本就在20名左右徘徊。但是,三天以來,從第一天思維僵化忽略各種情況到今天想到第二題正解 雖然寫掛了 個人感覺自己的狀態還是在變好,並且收穫了一些乾貨 1.對於輸入輸出接近longlong的題目,不要因...

判別三連之三 Spark 分布式實現貝葉斯判別

假 設事 件b1,b2.bn是 樣本空間 的乙個 分割,且 他們各自 的概率為 p b1 p b2 p bn 假設事件 b 1,b 2.b n 是樣本空間 的乙個分割,且他們各自的概率為p b 1 p b 2 p b n 假設事件b1 b2 bn 是 樣本空間 的乙個 分割,且 他們各自 的概率為 ...