在寻找最优解时没多大问题,但最劣解我硬是死磕了一天没弄出来
最初是因为参照最优解码最劣解导致的46分,可是当我参照 @Mubuky 奆佬的思路,即在能够不更新的情况下优先探索编号小的节点,反之则找编号大的节点,最后发现答案全WA......
代码奉上
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 500005
#define inf 0x7fffffff
int n,m,num,head[N],in1[N],in2[N],min1,min2,ans1,ans2;
bool b[N];
priority_queue<int,vector<int>,greater<int> >h1;//最优 小根堆
priority_queue<int> hh1;//最劣 大根堆
priority_queue<int,vector<int>,greater<int> > hh2;//最劣 小根堆
struct Edge{
int to;
int next;
}edge[N];
void Addedge(int x,int y)
{
edge[++num].to=y;
edge[num].next=head[x];
head[x]=num;
}
int main()
{
ios::sync_with_stdio(false);
memset(head,0,sizeof(head));
memset(in1,0,sizeof(in1));
memset(in2,0,sizeof(in2));
memset(b,false,sizeof(b));
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
Addedge(x,y);
in1[y]++;in2[y]++;
}
min1=0;min2=0;
//最优解
for(int i=1;i<=n;i++)
if(!in1[i])h1.push(i);
while(!h1.empty())
{
int fro=h1.top();h1.pop();
if(min1<fro)min1=fro,ans1++;
for(int i=head[fro];i;i=edge[i].next)
{
in1[edge[i].to]--;
if(!in1[edge[i].to])
h1.push(edge[i].to);
}
}
cout<<ans1<<'\n';
//最劣解
for(int i=1;i<=n;i++)
if(!in2[i]){hh1.push(i);hh2.push(i);b[i]=true;}
while((!hh1.empty())&&(!hh2.empty()))
{
while(!b[hh1.top()])hh1.pop();
while(!b[hh2.top()])hh2.pop();
if(hh2.top()>min2)//当前必须付出筹码
{
int fro=hh1.top();//找最大点
hh1.pop();b[fro]=false;//最大点已离队
ans2++;
for(int i=head[fro];i;i=edge[i].next)
{
in2[edge[i].to]--;
if(!in2[edge[i].to]){hh1.push(edge[i].to);hh2.push(edge[i].to);b[edge[i].to]=true;}
}
}
else if(hh2.top()<=min2)//当前没必要付出筹码
{
int fro=hh2.top();
hh2.pop();b[fro]=false;
for(int i=head[fro];i;i=edge[i].next)
{
in2[edge[i].to]--;
if(!in2[edge[i].to]){hh1.push(edge[i].to);hh2.push(edge[i].to);b[edge[i].to]=true;}
}
}
}
cout<<ans2<<'\n';
return 0;
}
望奆佬解惑
原题:P5603 小C与桌游