[SDOI2011]工作安排
阿新 • • 發佈:2018-12-07
原題的話,由於保證了wi<wi+1,是一個比較simple的費用流啦。
如果不保證wi遞增的話,也可以有一個比較暴力的複雜度和流量相關的做法。
#include<iostream> #include<cctype> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<queue> #include<cstdlib> #include<algorithm> #define N 220000 #define M 220000 #define L 200000 #define eps 1e-7 #define inf 1e9+7 #define ll long long using namespace std; inline int read() { char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*flag; } struct edge { int to,nxt,flow,w; }e[M]; int num,head[N]; inline void add(int x,int y,int w,int z) { e[++num]=(edge){y,head[x],w,+z};head[x]=num; e[++num]=(edge){x,head[y],0,-z};head[y]=num; } queue<int>q; bool in_queue[N]; int s,t,T[N],W[N],dis[N],pre[N],last[N],flow[N]; bool spfa() { for(int i=0;i<=t;i++)dis[i]=flow[i]=inf; dis[s]=0;q.push(s);in_queue[s]=true; while(!q.empty()) { int x=q.front(); q.pop();in_queue[x]=false; for(int i=head[x];i!=-1;i=e[i].nxt) { int to=e[i].to; if(dis[to]>dis[x]+e[i].w&&e[i].flow) { dis[to]=dis[x]+e[i].w; flow[to]=min(flow[x],e[i].flow); pre[to]=x;last[to]=i; if(!in_queue[to])q.push(to),in_queue[to]=true; } } } return dis[t]<inf; } void dfs(int x) { if(x==s)return; int id=last[x]; e[id].flow-=flow[t]; e[id^1].flow+=flow[t]; dfs(pre[x]); } int main() { num=-1;memset(head,-1,sizeof(head)); int m,n; m=read();n=read();s=n+m+1;t=n+m+2; for(int i=1;i<=n;i++)add(i+m,t,read(),0); for(int i=1;i<=m;i++)for(int j=1;j<=n;j++) if(read())add(i,j+m,inf,0); for(int i=1;i<=m;i++) { int k=read(); for(int j=1;j<=k;j++)T[j]=read();T[k+1]=inf; for(int j=1;j<=k+1;j++)W[j]=read(); for(int j=1;j<=k+1;j++)add(s,i,T[j]-T[j-1],W[j]); } ll ans=0; while(spfa()) { ans+=dis[t]*flow[t]; dfs(t); } printf("%lld",ans); return 0; }