洛谷題面
看到很多題解並沒有講清楚這道題為什麼可以用某些方法,套個板子就沒了。蒟蒻就發一篇題解裝x造福大家吧233
做這道題前,我推薦大家做一下一本通中的1352:【例4-13】獎金一題,因為有可能做完了這道題對於你們會有一點啟發。
題目分析題目對於小朋友的嫉妒一共有\(5\)中情況,分別如下:
·如果 x=1, 表示第 a 個小朋友分到的糖果必須和第 b 個小朋友分到的糖果一樣多;
·如果 x=2, 表示第 a 個小朋友分到的糖果必須少於第 b 個小朋友分到的糖果;
·如果 x=3, 表示第 a 個小朋友分到的糖果必須不少於第 b 個小朋友分到的糖果;
·如果 x=4, 表示第 a 個小朋友分到的糖果必須多於第 b 個小朋友分到的糖果;
·如果 x=5, 表示第 a 個小朋友分到的糖果必須不多於第 b 個小朋友分到的糖果;
題目想要讓每個小朋友都滿足且使用最少的糖果數量,如果無解則輸出-1。
我們將小朋友當做點,小朋友之間限制條件當做邊
對於x=1、x=3、x=5時,我們不難知道,想要使用最少的糖果數量,那麼最好的方式就是兩個人糖果數量一樣。
對於x=2,那麼a=b-1最優
對於x=4,那麼b=a-1最優
所以說了做一下一本通中的1352:【例4-13】獎金一題對於你們會有一點啟發。
現在我們又可以想到,讓每個小朋友都滿足且使用最少的糖果數量,那麼只需要通過別人對它沒有限制的小朋友,依次更新每個小朋友要有的糖即可。
那麼怎麼去依次找小朋友並更新每個小朋友要的糖呢?拓撲排序!
怎麼建圖?按什麼條件去建?比如a要少於b,則建一條a->b的邊,這樣拓撲排序下來,可以保證處理每個點的糖果數量時,可以從小處理到大,符合上面的要求。
那x=1、3、5和x=2、4時有什麼區別呢?我們就需要額外記錄邊權,x=1、3、5邊權為0,x=2、4邊權為1。
血的教訓:x=1時需要建雙向邊!即a->b且b->a。
為什麼?因為a必須與b一樣多,那麼我們就可以使用tarjan縮點將兩個點合併為1個點,且將環變為強連通分量。正好滿足了拓撲排序不能有環的性質。
怎麼判斷無解情況?在建新圖用來拓撲排序時,看兩個點是否在同乙個環內,在且邊權為1則無解。
最重要的乙個問題:怎麼更新糖果數量?我們將每個人的糖果當做dp[i],在刪i相連的點的入度時,更新i的next的dp值
則有動態轉移方程:
dp[當前更新的點] = max(dp[當前更新的點],dp[當前刪除的點] + nnei[當前刪除的點][第j個鄰居].邊權)
這些知識本人blog中都會涉及的233
那麼思路就很明顯了:
建圖(x=1:建邊權為0的雙向邊,x=2、x=4建邊權為1的單向邊,x=3、x=5時建邊權為0的單向邊)——>tarjan——>邊建新圖邊判斷無解——>用新圖拓撲排序,並更新每個點所需要的糖果數量
**#includeusing namespace std;
const int maxn = 100000 + 10;
int n,k;
int scc[maxn],sum,low[maxn],dfn[maxn],cnt,tot[maxn];
//以上是強連通圖的必備變數,唯一tot是記錄每個強連通分量裡面有多少個點
int dp[maxn];
//這個用於dp記錄答案
int in[maxn];
//這個記錄入度,用於topo
long long ans;
//最終答案
struct node;
vectornei[maxn];//舊圖
vectornnei[maxn];//新圖
bool stack[maxn];//用於tarjan
stacks;//用於tarjan
inline int read()
while (c >= '0' && c <= '9')
return f * x;
}void tarjan(int u)else
if(stack[next]) }
if(dfn[u] == low[u])
s.pop(); }}
int main()
); nei[y].push_back((node));
//這裡一定要建兩條邊!
break;
}case 2:);
break;
}case 3:);
break;
}case 4:);
break;
}case 5:);
break;
}} }
for(int i = 1;i <= n; i++)
for(int i = 1;i <= n; i++)
if(xx != yy));
in[yy]++;
}} }
queueq;//topo模板
for(int i = 1;i <= sum; i++) }
while(!q.empty()) }
for(int i = 1;i <= sum; i++)
cout<**不做非常詳細的注釋,自己對照前面詳細的講解看看吧233
感謝我的教練 @livedream 幫我debug!
題解 SCOI2011 糖果
依舊是比較明顯的差分約束 注意對於五種操作分別對應的連邊方式 然後注意head的初始值判斷,要不然總是超時 今天遇到好幾次了 建圖時加個小剪枝,否則會tle 1 include2 include3 include4 include5 include6 using namespace std 7con...
SCOI 2011 糖果 SPFA 差分約束
description 幼兒園裡有n個小朋友,lxhgww老師現在想要給這些小朋友們分配糖果,要求每個小朋友都要分到糖果。但是小朋友們也有嫉妒心,總是會提出一些要求,比如小明不希望小紅分到的糖果比他的多,於是在分配糖果的時候,lxhgww需要滿足小朋友們的k個要求。幼兒園的糖果總是有限的,lxhgw...
差分約束詳解 洛谷SCOI2011糖果題解
差分約束系統 如果乙個系統由n個變數和m個約束條件組成,形成m個形如ai aj k的不等式 i,j 1,n k為常數 則稱其為差分約束系統 system of difference constraints 亦即,差分約束系統是求解關於一組變數的特殊不等式組的方法。度娘。然而並沒有看懂。通俗來說,滿足...