BZOJ 3876([Ahoi2014]支线剧情-带下界的最小费用可行流)
2016-05-19 01:03
387 查看
题意:给定一张带边权DAG,每次只能从第一个点出发沿着拓扑图走一条路径,求遍历所有边所需要的最小边权和。
设起点1,终点t=n+1
每条边容量下界为1
有源有汇的图,终点连一条边到起点,容量为INF,变成无源无汇
必须满流的边(u,v,w):建立超源S,超汇T,连接(S,v,w),(u,T,w),流量平衡就行
PoPoQQQ
blog.csdn.net/popoqqq/article/details/43024221
建图如下:
对于每一条边权为z的边x->y:
从S到y连一条费用为z,流量为1的边 代表这条边至少走一次
从x到y连一条费用为z,流量为INF的边 代表这条边除了至少走的一次之外还可以随便走
对于每个点x:
从x到T连一条费用为0,流量为x的出度的边
从x到1连一条费用为0,流量为INF的边,代替原图上的源和汇
直接跑费用流
设起点1,终点t=n+1
每条边容量下界为1
有源有汇的图,终点连一条边到起点,容量为INF,变成无源无汇
必须满流的边(u,v,w):建立超源S,超汇T,连接(S,v,w),(u,T,w),流量平衡就行
PoPoQQQ
blog.csdn.net/popoqqq/article/details/43024221
建图如下:
对于每一条边权为z的边x->y:
从S到y连一条费用为z,流量为1的边 代表这条边至少走一次
从x到y连一条费用为z,流量为INF的边 代表这条边除了至少走的一次之外还可以随便走
对于每个点x:
从x到T连一条费用为0,流量为x的出度的边
从x到1连一条费用为0,流量为INF的边,代替原图上的源和汇
直接跑费用流
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (600+10) #define MAXM ((15400)*3+10) #define MAXAi (35000) #define eps (1e-3) long long mul(long long a,long long b){return (a*b)%F;} long long add(long long a,long long b){return (a+b)%F;} long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} typedef long long ll; class Cost_Flow { public: int n,s,t; int q[MAXM]; int edge[MAXM],next[MAXM],pre[MAXN],weight[MAXM],size; int cost[MAXM]; void addedge(int u,int v,int w,int c) { edge[++size]=v; weight[size]=w; cost[size]=c; next[size]=pre[u]; pre[u]=size; } void addedge2(int u,int v,int w,int c){addedge(u,v,w,c),addedge(v,u,0,-c);} bool b[MAXN]; int d[MAXN]; int pr[MAXN],ed[MAXN]; bool SPFA(int s,int t) { For(i,n) d[i]=INF,b[i]=0; d[q[1]=s]=0;b[s]=1; int head=1,tail=1; while (head<=tail) { int now=q[head++]; Forp(now) { int &v=edge[p]; if (weight[p]&&d[now]+cost[p]<d[v]) { d[v]=d[now]+cost[p]; if (!b[v]) b[v]=1,q[++tail]=v; pr[v]=now,ed[v]=p; } } b[now]=0; } return d[t]!=INF; } int totcost; int CostFlow(int s,int t) { while (SPFA(s,t)) { int flow=INF; for(int x=t;x^s;x=pr[x]) flow=min(flow,weight[ed[x]]); totcost+=flow*d[t]; for(int x=t;x^s;x=pr[x]) weight[ed[x]]-=flow,weight[ed[x]^1]+=flow; } return totcost; } void mem(int n,int t) { (*this).n=n; size=1; totcost=0; MEM(pre) MEM(next) } }S1; int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } int n; int main() { // freopen("bzoj3876.in","r",stdin); // freopen(".out","w",stdout); n=read(); int s=1,t=n+1,S=n+2,T=n+3; S1.mem(T,T); const int inf = INF; For(i,n) { int m=read(); S1.addedge2(i,t,inf,0); For(j,m) { int v=read(),c=read(); S1.addedge2(i,v,inf,c); S1.addedge2(S,v,1,c); S1.addedge2(i,T,1,0); } } S1.addedge2(t,s,inf,0); //无源无汇,保证流量守恒 cout<<S1.CostFlow(S,T)<<endl; return 0; }
相关文章推荐
- PHP中count()和sizeof()
- PAT乙级真题及训练题 1025. 反转链表 (25)
- Spring的事务和Hibernate的事务有什么区别
- stm8 在IAR 下烧写出现The Flash Memory Read-out protection 的解决方法
- STL源码解析 - nth_element
- 无代理不框架,浅析JDK和Cglib动态代理
- (Solved)Unable to change back light on Ubuntu 14.04 on Samsung Laptop
- ListView使用总结
- 在jdk 1.6版本中,switch的参数无法使用String类型
- URAL 1990 Podracing(尺取法)
- C++中的内联函数inline总结
- C3p0源码探索(一)之配置篇
- RecyclerView绘制原理探究
- vscode编写插件详细过程
- 前端案例--简易弹幕效果
- tomat优化
- Java中Properties类的使用
- 黑客常用命令大全
- strace命令 来自: http://man.linuxde.net/strace
- jQuery1.9.1源码分析--数据缓存Data模块