昨天晚上 ABC 的 G 脑抽了跑了 150 遍费用流,然后直接 T 飞,赛后马上就想到每次增广只会多一流量,所以记录每次增广的费用即可。
今天看见最短解 500kb 左右,发现 #include <atcoder/all>,就想着用一用试试。
结果发现这个已经封装好了,只能 g.flow(),怎么做才能用这个标准库做到每次增广都记录答案呢?
附 最短解榜一老哥代码
#include<atcoder/all>
using namespace std;
int main(){
int n;
cin>>n;
atcoder::mcf_graph<int,long>g(333);
long o=1e12;
for(int i=1;i<=150;i++)g.add_edge(0,i,1,0),g.add_edge(150+i,321,1,0);
for(int i=0;i<n;i++){
int a,b,c;
cin>>a>>b>>c;
g.add_edge(a,150+b,1,o-c);
}
int k=1;
vector<long>v;
for(;;k++){
auto G=g;
auto[f,c]=G.flow(0,321,k);
if(f<k)break;
v.push_back(o*k-c);
}
cout<<v.size()<<'\n';
for(auto x:v)cout<<x<<'\n';
}
1289 ms,可以看到这位老哥打的也是暴力,然后因为标准库常熟小所以过了,我是大常数选手所以没过
然后榜二 45 ms,似乎只跑了一次费用流,然后用了奇怪的函数 g.slope,看不懂所以来求助谷友。
#include<atcoder/all>
using namespace std;
const long inf=1<<30;
main(){
int n;
cin>>n;
atcoder::mcf_graph<int,long>G(302);
for(int i=0;i<150;i++){
G.add_edge(300,i,1,0);
G.add_edge(150+i,301,1,0);
}
for(int i=0;i<n;i++){
int a,b,c;
cin>>a>>b>>c;
a--,b--;
G.add_edge(a,150+b,1,inf-c);
}
auto F=G.slope(300,301);
cout<<F.back().first<<'\n';
int x=0;
long y=0;
for(auto[p,q]:F){
if(!p)continue;
long d=(q-y)/(p-x);
while(x<p){
x++;
y+=d;
cout<<(inf*x-y)<<'\n';
}
}
}