HDU 4067 Random Maze
来源:互联网 发布:跳跃网络次元大作战 编辑:程序博客网 时间:2024/05/16 19:50
题意:给出一个有n个点m条边的有向图,现在要从图中删去一些边使得图满足以下条件:
1.图中只有一个入口(s)和一个出口(t)
2.所以边都是单向的(这个原图已经保证了)
3.对入口(s)而言,其出度=入度+1
4.对出口(t)而言,其入度=出度+1
5.对入口(s)、出口(t)以外的点,其入度=出度
重新为每个边建立权值!
1.如果有边(u,v,a,b) 并且a<=b,那么建立边(v,u,1,b-a) sum+=a,如果要恢复此边需花费 b-a 的费用;in[u]++,out[v]++;
2.如果有边(u,v,a,b) 并且a>b,那么建立边(u,v,1,a-b) sum+=b,如果要删除此边需花费 a-b 的费用;
3.另需t和s 建立一条虚边,in[s]++,out[t]++;
最后建立一个超级源点S 和超级汇点T,则如果对于点 i in[i]>out[i] 那么建立边(S,i,in[i]-out[i],0);
相反 建立边(i,T,out[i]-in[i],0);
最小费用最大流后,如果max_flow=到汇点t所有容量只和 答案即为:sum+max_flow;
1.图中只有一个入口(s)和一个出口(t)
2.所以边都是单向的(这个原图已经保证了)
3.对入口(s)而言,其出度=入度+1
4.对出口(t)而言,其入度=出度+1
5.对入口(s)、出口(t)以外的点,其入度=出度
而对图中每条边,保留这条边或者删去这条边都有相应的花费,分别为a、b,求使得该图满足条件的最小花费。
重新为每个边建立权值!
1.如果有边(u,v,a,b) 并且a<=b,那么建立边(v,u,1,b-a) sum+=a,如果要恢复此边需花费 b-a 的费用;in[u]++,out[v]++;
2.如果有边(u,v,a,b) 并且a>b,那么建立边(u,v,1,a-b) sum+=b,如果要删除此边需花费 a-b 的费用;
3.另需t和s 建立一条虚边,in[s]++,out[t]++;
最后建立一个超级源点S 和超级汇点T,则如果对于点 i in[i]>out[i] 那么建立边(S,i,in[i]-out[i],0);
相反 建立边(i,T,out[i]-in[i],0);
最小费用最大流后,如果max_flow=到汇点t所有容量只和 答案即为:sum+max_flow;
否则 impossible;
#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define CLR(x,y) memset(x,y,sizeof(x))#define mp(x,y) make_pair(x,y)#define eps 1e-9#define INF 0x3f3f3f3fusing namespace std;typedef long long ll;typedef long double ld;typedef pair<ll, ll> pll;typedef complex<ld> point;typedef pair<int, int> pii;typedef pair<pii, int> piii;template<class T>inline bool read(T &n){ T x = 0, tmp = 1; char c = getchar(); while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if(c == EOF) return false; if(c == '-') c = getchar(), tmp = -1; while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar(); n = x*tmp; return true;}template <class T>inline void write(T n){ if(n < 0) { putchar('-'); n = -n; } int len = 0,data[20]; while(n) { data[len++] = n%10; n /= 10; } if(!len) data[len++] = 0; while(len--) putchar(data[len]+48);}//-----------------------------------const int M=5010;const int N=111;int in[N]; //入度和出度的差int n,m,s,t;struct Graph{ struct node { int v,next,w,flow; node() {}; node(int a,int b,int c,int d) { next=a; v=b; w=c; flow=d; } } E[2*M]; int head[N],pre[N],dis[N]; int beg,end,flow,cost; bool h[N]; int path[N]; int NE,NV; void resize(int n) { this->NV=n; } void init(int n) { NE=0; NV=n; memset(head,-1,sizeof(int)*(n+10)); } void insert(int u,int v,int flow,int w) { E[NE]=node(head[u],v,w,flow); head[u]=NE++; E[NE]=node(head[v],u,-w,0); head[v]=NE++; } bool update(int u,int v,int w) { if(dis[u]+w<dis[v]) { dis[v]=dis[u]+w; return true; } return false; } bool spfa() { CLR(pre,-1); CLR(h,0); for(int i=0; i<=NV; i++) dis[i]=INF; dis[beg]=0; queue<int> q; q.push(beg); while(!q.empty()) { int u=q.front(); q.pop(); h[u]=0; for(int i=head[u]; i!=-1; i=E[i].next) { int v=E[i].v; if(E[i].flow>0&&update(u,v,E[i].w)) { pre[v]=u; path[v]=i; if(!h[v]) { h[v]=1; q.push(v); } } } } if(pre[end]==-1) return false; return true; } int mincost_maxflow(int s,int t) { this->beg=s; this->end=t; flow=0,cost=0; while(spfa()) { int Min=INT_MAX; for(int i=end; i!=beg; i=pre[i]) if(Min>E[path[i]].flow) Min=E[path[i]].flow; for(int i=end; i!=beg; i=pre[i]) { E[path[i]].flow-=Min; E[path[i]^1].flow+=Min; } flow+=Min; cost+=dis[end]; } return cost; }} g;int main(){ int T,cas=1; read(T); while(T--) { read(n),read(m),read(s),read(t); g.init(n+2); memset(in,0,sizeof(in)); in[s]++,in[t]--; int u,v,a,b,ss=0,tt=n+1,sum=0,cnt=0; for(int i=1;i<=m;i++) { read(u),read(v),read(a),read(b); if(a>=b) { g.insert(u,v,1,a-b); // 删除(如果流过则不删) sum+=b; } else { g.insert(v,u,1,b-a); // 不删除(如果流过则删除,加一条反边中和入度出度) sum+=a; in[u]--,in[v]++; } } for(int i=1;i<=n;i++) // 保留入度,计算出度 { if(in[i]>0) g.insert(ss,i,in[i],0); else { g.insert(i,tt,-in[i],0); cnt+=-in[i]; } } sum+=g.mincost_maxflow(ss,tt); printf("Case %d: ",cas++); if(g.flow==cnt) write(sum),putchar('\n'); else puts("impossible"); } return 0;}
0 0
- hdu 4067 Random Maze
- HDU 4067 Random Maze
- HDU 4067 Random Maze
- HDU 4067 Random Maze 费用流
- 【HDU】 4067 Random Maze 费用流
- hdu 4067Random Maze(费用流)
- HDU 4067 Random Maze 费用流
- HDU 4067 Random Maze(费用流)
- Random Maze HDU
- hdu 4067 Random Maze(最小费用最大流)
- hdu 4067 Random Maze(最小费用最大流)
- HDU 4067 Random Maze 最小费用最大流
- hdu 4067 Random Maze (费用流)(难)
- hdu 4067 Random Maze(最小费用流)
- hdu 4067 Random Maze 最小费用最大流
- HDU 4067 Random Maze 费用流 构造欧拉通路
- Random Maze - HDU 4067 最小费用最大流
- HDU 4067 Random Maze 最小费用最大流
- 2048
- spring组件扫描<context:component-scan/>使用详解 .
- ACM 222. [POI1997] 便宜的旅行(dp)
- 【Android】 RGB颜色对照表
- poj 2229 Ultra-QuickSort(树状数组)
- HDU 4067 Random Maze
- Android 快速开发系列 打造万能的ListView GridView 适配器
- zedboard上移植OPENCV库
- Spring事务的架构 .
- 测试用例实例--常见功能测试点
- poj 2251(广搜求两点之间的距离)
- 使用goto实现循环,跳转语句
- 表达式求值 NYOJ
- Word Ladder 宽搜超时 新方法未做!!!!!