题解 P5603 【小C与桌游】
首先,这道题显然和拓扑排序有关
知道了这一点,问题其实就解决了大半。
其次,读题后发现,题目要求求出 “最优情况” 和 “最劣情况” 两个答案
我们不妨在求解时将这两个问题分开。
对于“最优情况”,我们显然可以贪心的取编号最小的入度为
下面我主要讲“最劣情况”的求解。
对于“最劣情况”,能否再按照同上面方式的贪心(即把拓扑排序的
若按照先前的贪心,我们可以得到这样的一个扩展序列:
2 -> 3 -> 1 -> 4
ans = 3;
但存在这样一条扩展序列:
2 -> 1 -> 4 -> 3
ans = 2;
显然更优,这种解法出了问题,实际上这种解法加上“最优情况”的正解可以得到
那么如何求解呢?
我们看上面的反例,首先同拓扑排序找到入度为
接下来待扩展的节点有2个,(1)和(3),我们发现扩展(1)时答案(
现在待扩展的节点是(4)和(3),他们都大于max,都不能在答案不更新的前提下拓展。接下来不妨贪心的想,先拓展(4)再拓展(3),即取编号最大的点先扩展。
#include<queue>
#include<cstdio>
#include<vector>
using namespace std;
int in2[500001];//入度
vector<int>g[500001];//存图
priority_queue<int,vector<int>,less<int> >qless;
queue<int>kz;//kz(queue)待扩展序列
int main()
{
int maxn=0,ans=0;
while(!qless.empty()){
int x=qless.top();
if(x>maxn){
ans++;
}
while(!qless.empty()){
kz.push(qless.top());
qless.pop();
}
while(!kz.empty()){
int nx=kz.front();
kz.pop();
maxn=max(maxn,nx);
for(int j=0;j<g[nx].size();j++){
int y=g[nx][j];
in2[y]--;
if(in2[y]==0){
if(y>maxn){
qless.push(y);
}else{
kz.push(y);
}
}
}
}
}
printf("%d",ans);
return 0;
}
完整代码:
#include<queue>
#include<cstdio>
#include<vector>
using namespace std;
queue<int>kz;
priority_queue<int,vector<int>,greater<int> >qgreater;
priority_queue<int,vector<int>,less<int> >qless;
vector<int>g[500001];
int in[500001],in2[500001];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d %d",&u,&v);
g[u].push_back(v);
in[v]++;
in2[v]++;
}
for(int i=1;i<=n;i++){
if(in[i]==0){
qgreater.push(i);
qless.push(i);
}
}
//"最优情况"
int maxn=0,ans=0;
while(!qgreater.empty()){
int x=qgreater.top();
qgreater.pop();
if(x>maxn){
ans++;
}
maxn=max(maxn,x);
for(int j=0;j<g[x].size();j++){
int y=g[x][j];
in[y]--;
if(in[y]==0){
qgreater.push(y);
}
}
}
printf("%d\n",ans);
//"最劣情况"
maxn=0,ans=0;
while(!qless.empty()){
int x=qless.top();
if(x>maxn){
ans++;
}
while(!qless.empty()){
kz.push(qless.top());
qless.pop();
}
while(!kz.empty()){
int nx=kz.front();
kz.pop();
maxn=max(maxn,nx);
for(int j=0;j<g[nx].size();j++){
int y=g[nx][j];
in2[y]--;
if(in2[y]==0){
if(y>maxn){
qless.push(y);
}else{
kz.push(y);
}
}
}
}
}
printf("%d",ans);
return 0;
}
Update:感谢 @AxDea 和 @光明神 指出该篇题解样图分析中有关ans变量的问题