bzoj 1877: [SDOI2009]晨跑 费用流
2016-07-21 11:19
393 查看
题意:给出一个有向图,求从起点到终点最多能找到多少条不相交的路径和这些路径的最小总长度。
分析:
如果只有第一问的话就是拆点最大流
第二问就是裸的拆点费用流
费用流的原理就是每次找最小费用可增广路来进行增广(用spfa来实现)
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define inf 0x7fffffff
using namespace std;
int n,m,cnt=0,last[1001]={0},s,t,dis[1001],v[1001],q[1001],ans1=0,ans2=0,pre[1001];
struct data{int x,y,c,w,next,op;}e[100001];
void insert(int x,int y,int w,int c)
{
cnt++;
e[cnt].x=x;e[cnt].y=y;e[cnt].w=w;e[cnt].c=c;e[cnt].op=cnt+1;
e[cnt].next=last[x];last[x]=cnt;
cnt++;
e[cnt].x=y;e[cnt].y=x;e[cnt].w=0;e[cnt].c=-c;e[cnt].op=cnt-1;
e[cnt].next=last[y];last[y]=cnt;
}
bool spfa()
{
for (int i=s;i<=t;i++)
{
dis[i]=inf;
v[i]=0;
}
int head=0,tail=1;
q[1]=s;v[s]=1;dis[s]=0;
while(head!=tail)
{
if (head==1000)head=0;
head++;
int now=q[head],i=last[now];
while (i)
{
if (e[i].w&&dis[now]+e[i].c<dis[e[i].y])
{
dis[e[i].y]=dis[now]+e[i].c;
pre[e[i].y]=i;
if (!v[e[i].y])
{
v[e[i].y]=1;
if (tail==1000)tail=0;
tail++;
q[tail]=e[i].y;
}
}
i=e[i].next;
}
v[now]=0;
}
if (dis[t]==inf) return 0;
return 1;
}
void mcf()
{
int x=inf,i=t;
while (pre[i])
{
x=min(e[pre[i]].w,x);
i=e[pre[i]].x;
}
ans1++;
i=t;
while (i)
{
e[pre[i]].w-=x;
e[e[pre[i]].op].w+=x;
ans2+=e[pre[i]].c*x;
i=e[pre[i]].x;
}
}
int main()
{
scanf("%d%d",&n,&m);
s=1;t=n+n;
for (int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u+n,v,1,w);
}
for (int i=2;i<n;i++)insert(i,i+n,1,0);
insert(s,s+n,inf,0);
insert(n,t,inf,0);
while(spfa())mcf();
printf("%d %d\n",ans1,ans2);
return 0;
}
分析:
如果只有第一问的话就是拆点最大流
第二问就是裸的拆点费用流
费用流的原理就是每次找最小费用可增广路来进行增广(用spfa来实现)
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define inf 0x7fffffff
using namespace std;
int n,m,cnt=0,last[1001]={0},s,t,dis[1001],v[1001],q[1001],ans1=0,ans2=0,pre[1001];
struct data{int x,y,c,w,next,op;}e[100001];
void insert(int x,int y,int w,int c)
{
cnt++;
e[cnt].x=x;e[cnt].y=y;e[cnt].w=w;e[cnt].c=c;e[cnt].op=cnt+1;
e[cnt].next=last[x];last[x]=cnt;
cnt++;
e[cnt].x=y;e[cnt].y=x;e[cnt].w=0;e[cnt].c=-c;e[cnt].op=cnt-1;
e[cnt].next=last[y];last[y]=cnt;
}
bool spfa()
{
for (int i=s;i<=t;i++)
{
dis[i]=inf;
v[i]=0;
}
int head=0,tail=1;
q[1]=s;v[s]=1;dis[s]=0;
while(head!=tail)
{
if (head==1000)head=0;
head++;
int now=q[head],i=last[now];
while (i)
{
if (e[i].w&&dis[now]+e[i].c<dis[e[i].y])
{
dis[e[i].y]=dis[now]+e[i].c;
pre[e[i].y]=i;
if (!v[e[i].y])
{
v[e[i].y]=1;
if (tail==1000)tail=0;
tail++;
q[tail]=e[i].y;
}
}
i=e[i].next;
}
v[now]=0;
}
if (dis[t]==inf) return 0;
return 1;
}
void mcf()
{
int x=inf,i=t;
while (pre[i])
{
x=min(e[pre[i]].w,x);
i=e[pre[i]].x;
}
ans1++;
i=t;
while (i)
{
e[pre[i]].w-=x;
e[e[pre[i]].op].w+=x;
ans2+=e[pre[i]].c*x;
i=e[pre[i]].x;
}
}
int main()
{
scanf("%d%d",&n,&m);
s=1;t=n+n;
for (int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u+n,v,1,w);
}
for (int i=2;i<n;i++)insert(i,i+n,1,0);
insert(s,s+n,inf,0);
insert(n,t,inf,0);
while(spfa())mcf();
printf("%d %d\n",ans1,ans2);
return 0;
}
相关文章推荐
- Jquery 用法总结
- Opencv图像识别从零到精通(12)-----滑动条控制直方图、对比度、亮度、图像相加
- Nodejs异步流程控制Async
- iOS静态库和动态库的区别
- memcache的最佳实践方案。
- VS2010 + QT5.5.1 环境配置
- spring RestTemplate用法详解
- redis数据类型List的安全队列和不安全队列
- iOS开发之理解iOS中的MVC设计模式
- 2016年7月21日
- 学生学籍管理系统_学生登陆系统查询与修改信息
- 移动浪潮下,看地推吧如何“霸占”行业新风口
- TCP/IP协议集合
- mac OS X10.11.5安装scikit-learn后运行出现ValueError: numpy.dtype has the wrong size的错误
- Linux的运行级别和chkconfig用法
- mysql 批量建库授权脚本
- WeakHashMap深入理解
- LeetCode 226. Invert Binary Tree
- mybatis DBmanager
- .net中的认证(authentication)与授权(authorization)