【ZJOI2010】【最大流】【最小费用最大流】网络扩容
2013-03-18 22:07
393 查看
第一问就是一个最大流的裸题。
第二问的话思维难度也不大,一开始加边的时候费用为0,然后如果原图有边,就加入一条对应的流量无限,费用为扩容费用的边,要注意的是如果有重边需要选择费用最小的一条,再加一个源点s,连边s-t,流量为k,费用为0的边,然后做一次最小费用最大流就可以了。
代码:
第二问的话思维难度也不大,一开始加边的时候费用为0,然后如果原图有边,就加入一条对应的流量无限,费用为扩容费用的边,要注意的是如果有重边需要选择费用最小的一条,再加一个源点s,连边s-t,流量为k,费用为0的边,然后做一次最小费用最大流就可以了。
代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1000 + 10; const int maxque = 300000; const int maxm = 200000; struct pnode { int d,c,w,pos; int next; }E[maxm]; int cur[maxn],dis[maxn],gap[maxn]; int head[maxn],pre[maxn],que[maxque]; int map[maxn][maxn]; bool vis[maxn],flag[maxn][maxn]; int NE = 0; int n,m,k; int s,t,nodenum; void init() { freopen("bzoj1834.in","r",stdin); freopen("bzoj1834.out","w",stdout); } void insert(int u,int v,int c,int w) { E[NE].c = c;E[NE].w = w;E[NE].pos = v;E[NE].d = u; E[NE].next = head[u];head[u] = NE++; E[NE].c = 0;E[NE].w = -w;E[NE].pos = u;E[NE].d = v; E[NE].next = head[v];head[v] = NE++; } void readdata() { memset(map,0x3f,sizeof(map)); memset(flag,false,sizeof(flag)); memset(E,0,sizeof(E)); memset(head,-1,sizeof(head)); s = 1,t = n,nodenum = n; scanf("%d%d%d",&n,&m,&k); for(int i = 1;i <= m;i++) { int u,v,c,w; scanf("%d%d%d%d",&u,&v,&c,&w); flag[u][v] = true; map[u][v] = min(map[u][v],w); insert(u,v,c,0); } } inline void checkmin(int &a,int b) { if(a == -1 || a > b)a = b; } int sap() { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); for(int i = 1;i <= nodenum;i++)cur[i] = head[i]; int u = pre[s] = s,maxflow = 0,aug = -1; gap[0] = nodenum; while(dis[s] < nodenum) { loop: for(int &i = cur[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && dis[u] == dis[v] + 1) { checkmin(aug,E[i].c); pre[v] = u; u = v; if(v == t) { maxflow += aug; for(u = pre[u];v != s;v = u,u = pre[u]) { E[cur[u]].c -= aug; E[cur[u]^1].c += aug; } aug = -1; } goto loop; } } int mind = nodenum; for(int i = head[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && (mind > dis[v])) { cur[u] = i; mind = dis[v]; } } if((--gap[dis[u]]) == 0)break; gap[dis[u] = mind + 1]++; u = pre[u]; } return maxflow; } int spfa() { int l,r; memset(pre,-1,sizeof(pre)); memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[s] = 0; l = 0,r = 0; que[r++] = s; vis[s] = true; while(l < r) { int u = que[l++];l %= maxque; vis[u] = false; for(int i = head[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && dis[u] + E[i].w < dis[v]) { dis[v] = dis[u] + E[i].w; pre[v] = i; if(!vis[v]) { vis[v] = true; que[r++] = v;r %= maxque; } } } } if(dis[t] == inf)return false; else return true; } int mcmf() { int ret = 0,flow = 0; while(spfa()) { int u = t; int min = inf; while(u != s) { if(E[pre[u]].c < min)min = E[pre[u]].c; u = E[pre[u]].d; } flow += min; u = t; while(u != s) { E[pre[u]].c -= min; E[pre[u]^1].c += min; u = E[pre[u]].d; } ret += dis[t] * min; } return ret; } void solve() { s = 1,t = n,nodenum = n; printf("%d ",sap()); insert(0,1,k,0); for(int u = 1;u <= n;u++) { for(int v = 1;v <= n;v++) { if(flag[u][v])insert(u,v,inf,map[u][v]); } } s = 0,t = n; printf("%d\n",mcmf()); } int main() { init(); readdata(); solve(); return 0; }
相关文章推荐
- [BZOJ1834][ZJOI2010][最大流][最小费用最大流]网络扩容
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
- 【BZOJ1834】[ZJOI2010]network 网络扩容【最大流】【最小费用最大流】【残量网络】
- bzoj 1834: [ZJOI2010]network 网络扩容【最大流+最小费用最大流】
- 【bzoj1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
- [bzoj1834][ZJOI2010] 网络扩容 最大流 费用流
- [BZOJ1834][ZJOI2010]network 网络扩容(最大流+费用流)
- bzoj1834: [ZJOI2010]network 网络扩容(最小费用最大流)
- BZOJ1834 [ZJOI2010]network 网络扩容(最小费用最大流)
- [BZOJ1834]ZJOI2010网络扩容|最大流|费用流
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
- bzoj1834[ZJOI2010]network 网络扩容【最大流+费用流】
- 【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容
- Bzoj:[ZJOI2010]network 网络扩容:网络流,最大流+费用流
- 【COGS】1325 [ZJOI2010] 网络扩容 最大流+费用流
- [ZJOI2010]网络扩容 (最大流 + 费用流)
- [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流
- 【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)
- bzoj1834 [ZJOI2010]network 网络扩容 最大流+费用流
- BZOJ1834 [ZJOI2010]network 网络扩容 【最大流,费用流】