CF802C Heidi and Library (hard)

题意同https://www.luogu.org/problemnew/show/P4404,稍有改动

连边方法感觉贼神仙想不到,每个流的意义是一个空的书架。

每一天拆成两个点\(A_i,B_i\),连\((S,A_i,1,c_{a_i}),(A_i,B_i,1,-inf),(B_i,T,1,0)\)

然后对两天\(i<j\),如果\(a_i=a_j\),连\((B_i,A_j,1,0)\),否则连\((B_i,A_j,1,c_{a_j})\),表示书架的这个位置第\(i\)天用完了第\(j\)天再用(连向\(T\)代表不会再用了)

总费用加上\(n*inf\)就是答案了(inf是用来保证一定流这条边的)

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int fir[170],dis[100010],nxt[100010],w[100010],id=1,S,T;
ll cost[100010];
il vd link(int a,int b,int c,ll d){
    nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d;
    nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0,cost[id]=-d;
}
il vd Mincost(ll&totalcost){
    static int que[170],hd,tl,lst[170];
    static ll dist[170];
    static bool inq[170];
    hd=tl=0;que[tl++]=S;inq[S]=1;
    for(int i=1;i<=T;++i)dist[i]=1e18;
    dist[S]=0;
    while(hd^tl){
        int x=que[hd];
        for(int i=fir[x];i;i=nxt[i])
            if(w[i]&&dist[dis[i]]>dist[x]+cost[i]){
                dist[dis[i]]=dist[x]+cost[i],lst[dis[i]]=i;
                if(!inq[dis[i]]){
                    inq[dis[i]]=1,que[tl++]=dis[i];
                    if(tl==110)tl=0;
                }
            }
        inq[x]=0,++hd;
        if(hd==170)hd=0;
    }
    if(dist[T]>0)return;
    for(int i=lst[T];i;i=lst[dis[i^1]])totalcost+=cost[i],--w[i],++w[i^1];
}
int a[81],c[81];
int main(){
    int n=gi(),k=gi();S=n+n+1,T=n+n+2;
    for(int i=1;i<=n;++i)a[i]=gi();
    for(int i=1;i<=n;++i)c[i]=gi();
    for(int i=1;i<=n;++i)link(S,i,1,c[a[i]]),link(i,i+n,1,-1e9),link(i+n,T,1,0);
    for(int i=1;i<=n;++i)
        for(int j=i+1;j<=n;++j)
            link(i+n,j,1,a[i]==a[j]?0:c[a[j]]);
    ll ans=1e9*n;
    if(k>n)k=n;while(k--)Mincost(ans);
    printf("%lld\n",ans);
    return 0;
}
posted @ 2018-12-12 17:32  菜狗xzz  阅读(236)  评论(0编辑  收藏  举报