[CEOI2008]order 网络流(最小割)

题目传送门

蜜汁卡常数,,,

我把我能想到的各种方法都试了一遍,终于1332msA了,,(我承认写得丑+1)

如果没有租机器这种恶心到毁天灭地这种操作,这题就是裸的最小割模板了。(详情参考太空飞行计划问题

然而它有这种操作啊,,

回忆最小割模板,我们把工作和它对应的机器间连边,流量为inf(你不能只工作不买机器对吧)。现在,我可以只租用它(租用只对当前工作生效一次),就不用买,花费改为租用花费,然后跑最小割模板就行了。

ps:记得手写队列,,被卡死了N次我才记起来我用的STL,,

还有,bfs和dfs能直接返回的就直接返回,能减时间就减(恶心到毁天灭地,,)。最后数组问题,边数开2000000会RE,别问我怎么知道的。看着提交记录上一片RE我不想说话。推荐开3000000。对了,当前弧优化不用我提醒吧。

然后,上代码(?)

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define ll int
#define re register
#define inf 0x3f3f3f3f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug
");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
const ll mod=51123987;
const ll MAXN=505;
inl ll read() {
    re ll x = 0; re int f = 1;
    char ch = getchar();
    while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
    while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x * f;
}
inl char readc() {
    char ch=getchar();
    while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
    return ch;
}
inl void write(re ll x){
    if(x>=10)write(x/10);
    putchar(x%10+'0');
}
inl void writeln(re ll x){
    if(x<0) {x=-x;putchar('-');}
    write(x); puts("");
}
inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
inl ll Lcm(re ll a,re ll b) {return a/gcd(a,b)*b;}
inl void FR() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
inl void FC() {
    fclose(stdin);
    fclose(stdout);
}
ll head[1205<<1],cur[1205<<1],cnt=1,s=0,t,ans;
struct edge {
    ll u,v,w,nxt;
}e[3000005];
inl void adde(ll u,ll v,ll w) {
    e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
    e[cnt].nxt=head[u];head[u]=cnt;
}
ll d[1205<<1];
ll q[4050];
bool bfs() {
    for(re ll i=s;i<=t;i++) d[i]=0;
    ll hd=0,tl=0;q[hd]=s;d[s]=1;tl++;
    while(hd<tl) {
        re ll x=q[hd];hd++;
        if(x==t) return true ;
        for(re ll h=head[x];h;h=e[h].nxt) {
            re ll v=e[h].v;
            if(e[h].w&&!d[v]) {
                q[tl++]=v;d[v]=d[x]+1;
                if(v==t) return true ;
            }
        }
    }
    return d[t];
}
inl ll dfs(ll x,ll limit) {
    if(x==t||!limit) return limit;
    ll used=0;
    for(re ll h=cur[x];h;h=e[h].nxt,cur[x]=h) {
        if(e[h].w&&d[e[h].v]==d[x]+1) {
            re ll t=dfs(e[h].v,min(limit-used,e[h].w));
            e[h].w-=t;e[h^1].w+=t;used+=t;
            if(used==limit) break;
        }
    }
    if(!used) d[x]=0;
    return used;
}
int main() {
//  FR();
    re ll n=read(),m=read();t=n+m+1;s=0;
    for(re ll i=1;i<=n;i++) {
        re ll w=read(),x=read();
        adde(s,i,w);
        adde(i,s,0);
        ans+=w;
        for(re ll j=1;j<=x;j++) {
            re ll d=read();w=read();
            adde(i,d+n,w);
            adde(d+n,i,0);
        }
    }
    for(re ll i=1;i<=m;i++) {
        re ll w=read();
        adde(n+i,t,w);
        adde(t,n+i,0);
    }
    while(bfs()) {
        memcpy(cur,head,sizeof(head));
        ans-=dfs(s,inf);
    }
    writeln(ans);
//  FC();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/20020723YJX/p/9406395.html