【CF802C】Heidi and Library(網絡流)
阿新 • • 發佈:2019-03-06
names getch www. www 兩個 struct pty har 維護 連費用為\(-inf\)的邊,然後對於每個\(i'\),向後面的某天\(j\)連邊,表示這個位置下一次被使用的天,費用是如果不需要替換則是\(0\),否則是第\(j\)天的書的費用。
跑一個最小費用流就好了。
【CF802C】Heidi and Library(網絡流)
題面
CF
洛谷
題解
前面兩個Easy和Medium都是什麽鬼玩意啊。。。。
不難發現如果這天的要求就是第\(a_i\)種書的話,那麽\(a_i\)是必定要存在的。
把每種書拆\(n\)次,然後用每一個流維護一個書架上的位置,那麽這樣子很容易就可以連出費用流的建圖。
但是這樣子點數是平方級別,邊數是三方級別。
實際上書架上的位置是無序的,因此並不需要全部建出來,只需要考慮在哪些天會被替換。
考慮每本書下一次在什麽情況下會被使用,被使用有兩種情況,第一種是被換成了另外一本書,另外一種是沒有被替換。
所以把每天拆點,為了強制這天的書要選,所以從\(i\rightarrow i'\)
跑一個最小費用流就好了。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define MAX 85 const int inf=1e7; inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } namespace MCMF { const int MAXM=1000000,MAXN=1000; struct Line{int v,next,w,fy;}e[MAXM]; int h[MAXN],cnt=2; inline void Add(int u,int v,int w,int fy) { e[cnt]=(Line){v,h[u],w,fy};h[u]=cnt++; e[cnt]=(Line){u,h[v],0,-fy};h[v]=cnt++; } int dis[MAXN],pe[MAXN],pv[MAXN],Cost,Flow; bool vis[MAXN];queue<int> Que; int S=MAXN-2,T=MAXN-1; bool SPFA() { memset(dis,63,sizeof(dis));dis[S]=0; Que.push(S);vis[S]=true; while(!Que.empty()) { int u=Que.front();Que.pop(); for(int i=h[u];i;i=e[i].next) { int v=e[i].v;if(!e[i].w)continue; if(dis[u]+e[i].fy<dis[v]) { dis[v]=dis[u]+e[i].fy;pe[v]=i,pv[v]=u; if(!vis[v])vis[v]=true,Que.push(v); } } vis[u]=false; } if(dis[T]>=1e9)return false; int flow=1e9; for(int i=T;i!=S;i=pv[i])flow=min(flow,e[pe[i]].w); for(int i=T;i!=S;i=pv[i])e[pe[i]].w-=flow,e[pe[i]^1].w+=flow; Flow+=flow;Cost=min(Cost,Cost+dis[T]*flow); return true; } } using namespace MCMF; int n,K,a[MAX],c[MAX]; int main() { n=read();K=read(); for(int i=1;i<=n;++i)a[i]=read(); for(int i=1;i<=n;++i)c[i]=read(); for(int i=1;i<=n;++i)Add(S,i,1,c[a[i]]); for(int i=1;i<=n;++i)Add(i,i+n,1,-inf); for(int i=1;i<=n;++i)Add(i+n,T,1,0); for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) Add(i+n,j,1,a[i]==a[j]?0:c[a[j]]); Cost+=n*inf;K=min(K,n);while(K--)SPFA(); printf("%d\n",Cost); return 0; }
【CF802C】Heidi and Library(網絡流)