[SDOI2011]工作安排

来源:互联网 发布:药流对身体的影响 知乎 编辑:程序博客网 时间:2024/05/22 02:19

传送门
这个题我不知道为什么被卡到85,或许是我写的丑?
其实就是暴力拆点连边,分段函数就一段一条边就好了。
代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#define ll long longusing namespace std;inline int read(){    int x=0;char ch=' ';int f=1;    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-')f=-1,ch=getchar();    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();    return x*f;}const int N=1010,M=N*500;int m,n,s,t,tot=-1;int head[N],cur[N],inq[N],mark[N],q[M],d[N],to[M],Next[M],flow[M],cost[M];inline void addedge(int x,int y,int l,int c){    to[++tot]=y;Next[tot]=head[x];flow[tot]=l;cost[tot]=c;head[x]=tot;    to[++tot]=x;Next[tot]=head[y];flow[tot]=0;cost[tot]=-c;head[y]=tot;}inline bool spfa(){    for(int i=s;i<=t;i++)d[i]=0x3f3f3f3f,inq[i]=0;    int l=M/2,r=M/2;q[l]=s;d[s]=0;inq[s]=1;    while(l<=r){        int x=q[l++];        for(int i=head[x];i!=-1;i=Next[i]){            int u=to[i];            if(flow[i]&&d[u]>d[x]+cost[i]){                d[u]=d[x]+cost[i];                if(!inq[u]){                    inq[u]=1;                    if(d[u]<d[q[l]])q[--l]=u;                    else q[++r]=u;                }            }        }        inq[x]=0;    }    return d[t]!=0x3f3f3f3f;}ll C;inline int dfs(int x,int a){    mark[x]=1;    if(x==t||!a)return a;    int F=0,f;    for(int &i=cur[x];i!=-1;i=Next[i]){        int u=to[i];        if(!mark[u]&&flow[i]&&d[u]==d[x]+cost[i]&&(f=dfs(u,min(a,flow[i])))>0){            flow[i]-=f;            flow[i^1]+=f;            F+=f;            a-=f;            C+=f*cost[i];            if(!a)return F;        }    }    return F;}inline void MCMF(){    while(spfa()){        mark[t]=1;        while(mark[t]){            for(int i=s;i<=t;i++)mark[i]=0,cur[i]=head[i];            dfs(s,0x3f3f3f3f);        }    }}int T[N],W[N];int main(){    memset(head,-1,sizeof(head));    m=read();n=read();s=0;t=n+m+m+1;    for(int i=1;i<=n;i++){        int c=read();        addedge(s,i,c,0);    }    for(int i=1;i<=m;i++){        for(int j=1;j<=n;j++){            int can=read();            if(can)addedge(j,i+n,0x3f3f3f3f,0);        }    }    for(int i=1;i<=m;i++){        int cnt=read();        for(int j=1;j<=cnt;j++)T[j]=read();        for(int j=1;j<=cnt+1;j++)W[j]=read();        T[0]=0;T[cnt+1]=0x3f3f3f3f;        for(int j=1;j<=cnt+1;j++)addedge(i+n,i+n+m,T[j]-T[j-1],W[j]);        addedge(i+n+m,t,0x3f3f3f3f,0);    }    MCMF();    printf("%lld",C);    return 0;}
原创粉丝点击