标签:模板 set get min eof cas imp CMF read
这题应该算是比较难的一道网络流的题,(但却在我校OJ考试上出现了),但是大家只要能理解此图的建边方式就行。
假设有5天的租车需求,虚拟出2*n+2 即 12个节点,0为源点,12为汇点。
1,源点到1 2 3 4 5流量为r[i],费用为0。6 7 8 9 10到汇点流量为r[i-n],费用为0。
此题为一个检验能否满流且求满流花费最小的问题。
2,虚拟第2n+1个节点为买车途径,源点到2n+1节点花费为p[i],流量为c[i],多重边。
3,对于每一个i+n节点,其来源有两个,一个是
2*n+1节点,即购买新车,一个是之前的车辆送去维修后的可用车辆。连接i和i+1节点,流量为INF,花费为0。
4,同时根据维修的天数
连接i和d[j]+i+1+n节点,花费为s[i],流量为INF。
做完连边之后就跑一趟最小费用最大流模板,如最大流等于每天需要的车辆和,输出最小费用,否则,输出impossible。
#include<bits/stdc++.h>
using namespace std;
bool vis[400001];
int n,m,s,t,x,y,z,f,dis[400001],pre[400001],last[400001],flow[400001],maxflow,mincost,hh,hhh,ss,c,r,a[400001],b[400001];
struct Edge{
int to,next,flow,dis;
}edge[400001];
int head[400001],cnt;
queue <int> q;
void add(int from,int to,int flow,int dis)
{
edge[cnt].next=head[from];
edge[cnt].to=to;
edge[cnt].flow=flow;
edge[cnt].dis=dis;
head[from]=cnt++;
}
bool spfa(int s,int t)
{
memset(dis,0x7f,sizeof(dis));
memset(flow,0x7f,sizeof(flow));
memset(vis,0,sizeof(vis));
q.push(s); vis[s]=1; dis[s]=0; pre[t]=-1;
while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=0;
for (int i=head[now]; i!=-1; i=edge[i].next)
{
if (edge[i].flow>0 && dis[edge[i].to]>dis[now]+edge[i].dis)
{
dis[edge[i].to]=dis[now]+edge[i].dis;
pre[edge[i].to]=now;
last[edge[i].to]=i;
flow[edge[i].to]=min(flow[now],edge[i].flow);
if (!vis[edge[i].to])
{
vis[edge[i].to]=1;
q.push(edge[i].to);
}
}
}
}
return pre[t]!=-1;
}
void MCMF()
{
while(spfa(s,t))
{
int now=t;
maxflow+=flow[t];
mincost+=flow[t]*dis[t];
while(now!=s)
{
edge[last[now]].flow-=flow[t];
edge[last[now]^1].flow+=flow[t];
now=pre[now];
}
}
}
int read()
{
char ch=getchar();
int num=0;
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
num=num*10+ch-'0';
ch=getchar();
}
return num;
}
int main()
{
hh=read();
hhh=hh;
while(hh--)
{
maxflow=0;
mincost=0;
printf("Case %d: ",hhh-hh);
ss=0;
cnt=0;
memset(head,-1,sizeof(head));
n=read();
c=read();
r=read();
t=2*n+1;
s=0;
for(int i=1;i<=n;i++)
{
if(i!=n)
{
add(i,i+1,99999999,0);
add(i+1,i,0,0);
}
}
for(int i=1;i<=n;i++)
{
x=read();
add(i,t,x,0);
add(t,i,0,0);
add(s,i+n,x,0);
add(i+n,s,0,0);
ss+=x;
}
for(int i=1;i<=c;i++)
{
x=read();
y=read();
add(s,1,x,y);
add(1,s,0,-y);
}
for(int i=1;i<=r;i++)
{
a[i]=read();
b[i]=read();
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=r;j++)
{
if(i+a[j]+1<=n)
{
add(n+i,i+a[j]+1,99999999,b[j]);
add(i+a[j]+1,n+i,0,-b[j]);
}
}
}
MCMF();
if(maxflow==ss)
{
printf("%d\n",mincost);
}else{
puts("impossible");
}
}
}
标签:模板 set get min eof cas imp CMF read
原文地址:https://www.cnblogs.com/2017gdgzoi44/p/11324274.html