【网络流24题】餐巾计划问题

匿名 (未验证) 提交于 2019-12-02 23:49:02

建边有技巧啊,要拆点。
网络流建边的核心规律就是多做题一定是从源点到汇点,根据此构建模型即可。
\(dinic\) 实现最小费用流

/* @Date    : 2019-07-16 11:10:42 @Author  : Adscn (adscn@qq.com) @Link    : https://www.cnblogs.com/LLCSBlog */ #include<bits/stdc++.h> using namespace std; #define IL inline #define RG register #define gi getint() #define gc getchar() #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) IL int getint() {     RG int xi=0;     RG char ch=gc;     bool f=0;     while(ch<'0'|ch>'9')ch=='-'?f=1:f,ch=gc;     while(ch>='0'&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;     return f?-xi:xi; } template<typename T> IL void pi(T k,char ch=0) {     if(k<0)k=-k,putchar('-');     if(k>=10)pi(k/10,0);     putchar(k%10+'0');     if(ch)putchar(ch); } const int inf=2147483647,N=2007; int S=0,T; struct edge{int v,nxt,flow,w;}e[N<<2]; int head[N<<1],cnt; int cur[N<<1]; inline void add(int u,int v,int flow,int cost){e[cnt]=(edge){v,head[u],flow,cost};head[u]=cnt++;} inline void link(int u,int v,int flow,int cost){add(u,v,flow,cost);add(v,u,0,-cost);} int dis[N<<1]; bool vis[N<<1]; int spfa() {     memset(dis,127,sizeof dis);     memset(vis,0,sizeof vis);     static int Q[N<<1],l,r;     dis[Q[l=r=0]=S]=0;     while(l<=r)     {         int p=Q[l++];         vis[p]=0;         for(int i=head[p];~i;i=e[i].nxt)         {             int v=e[i].v;             if(dis[v]>dis[p]+e[i].w&&e[i].flow)             {                 dis[v]=dis[p]+e[i].w;                 if(!vis[v])Q[++r]=v,vis[v]=1;             }         }     }     return dis[T]<1e9; } long long ans; int dfs(int p,int restflow) {     if(p==T||restflow==0)return restflow;     int sumflow=0;     vis[p]=1;     for(int &i=cur[p],flow;(~i)&&restflow;i=e[i].nxt)     {         int v=e[i].v;         if(vis[v]==0&&e[i].flow&&dis[v]==dis[p]+e[i].w&&(flow=dfs(v,min(restflow,e[i].flow))))         {             sumflow+=flow,restflow-=flow;             e[i].flow-=flow,e[i^1].flow+=flow;             ans+=1ll*flow*e[i].w;         }     }     vis[p]=0;     return sumflow; } void dinic(){while(spfa())memcpy(cur,head,sizeof head),dfs(S,inf);} int main(void) {     #ifndef ONLINE_JUDGE     File("file");     #endif     int n=gi;T=n*2+1;     memset(head,-1,sizeof head);     for(int i=1;i<=n;++i)     {         int x=gi;         link(S,i,x,0);         link(i+n,T,x,0);     }     int newcost=gi,fastday=gi,fastcost=gi,slowday=gi,slowcost=gi;     for(int i=1;i<=n;++i)     {         if(i<n)link(i,i+1,inf,0);         if(i+slowday<=n)link(i,i+n+slowday,inf,slowcost);         if(i+fastday<=n)link(i,i+n+fastday,inf,fastcost);         link(S,i+n,inf,newcost);     }     dinic();     pi(ans);     return 0; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!