提交地址 Codeforces contest 100430
题面:
题意:你有 n n n 个文档要按给定顺序做(文档顺序构成一张 DAG),每个文档有 1 小时的工作量。现你有两个秘书,可让两个秘书分工做。问最小工作时间。
以样例为例:
按给定的顺序建一张图,那么工作顺序一定为拓扑序
首先,有个显然的结论,若合作一小时的,那么分工的形式一定是分成半小时和半小时
我们将每一份文档(1 个小时),拆成两份工作(半个小时和半个小时)
最优分工方式为
可得,每次在拓扑下,须优先选择最长链最长的点,考虑使用优先队列
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n,m,indeg[MAXN<<1];
vector <int> G[MAXN<<1];
bool mem[MAXN<<1];
int f[MAXN<<1];
int dfs(int u)
{
if(mem[u]) return f[u];
mem[u]=1;
int res=0;
for(auto v:G[u])
res=max(res,dfs(v));
return f[u]=res+1;
}
struct Node{
int id,val;
bool operator < (const Node &x)const{
return val<x.val;
}
};
priority_queue <Node> q;
int main()
{
freopen("documents.in","r",stdin);
freopen("documents.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)
G[i].push_back(i+n), indeg[i+n]++;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
G[u+n].push_back(v);
indeg[v]++;
}
for(int i=1;i<=(n<<1);i++)
if(!mem[i])
dfs(i);
for(int i=1;i<=n;i++)
if(indeg[i]==0)
q.push((Node){i,f[i]});
double ans=0;
while(!q.empty())
{
ans+=0.5;
bool flag1=0,flag2=0;
Node hd1,hd2;
if(!q.empty()) {hd1=q.top(); q.pop(); flag1=1;}
if(!q.empty()) {hd2=q.top(); q.pop(); flag2=1;}
if(flag1)
{
for(auto v:G[hd1.id]) {
indeg[v]--;
if(indeg[v]==0) q.push((Node){v,f[v]});
}
}
if(flag2)
{
for(auto v:G[hd2.id]) {
indeg[v]--;
if(indeg[v]==0) q.push((Node){v,f[v]});
}
}
}
cout<<ans;
return 0;
}