ZOJ 2364 Data Transmission (最大流:Dinic+贪心预流)
2013-09-25 13:50
417 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2364
裸的最大流。。。
用了Dinic、ISAP、HLPP都TLE。。。
然后在网上看到了个贪心预流的优化,就AC了,2030ms
贪心预流仅用于预处理分层图网络流
HLPP一般适合处理分层图,但是怎么加了贪心预流还是T了。。DINIC和ISAP加了贪心预流就AC了。。
同时附上Dinic和贪心预流模板~
View Code
裸的最大流。。。
用了Dinic、ISAP、HLPP都TLE。。。
然后在网上看到了个贪心预流的优化,就AC了,2030ms
贪心预流仅用于预处理分层图网络流
HLPP一般适合处理分层图,但是怎么加了贪心预流还是T了。。DINIC和ISAP加了贪心预流就AC了。。
同时附上Dinic和贪心预流模板~
//#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<iostream> #include<cstring> #include<string> #include<cmath> #include<set> #include<list> #include<map> #include<iterator> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<algorithm> #include<functional> using namespace std; typedef long long LL; #define ROUND(x) round(x) #define FLOOR(x) floor(x) #define CEIL(x) ceil(x) //const int maxn=0; //const int inf=0x3f3f3f3f; const LL inf64=0x3f3f3f3f3f3f3f3fLL; const double INF=1e30; const double eps=1e-6; /** *最大流最小割:加各种优化的Dinic算法($O(V^2E)$) *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇) *输出:Dinic(NdFlow)(最大流),MinCut()(最小割)(需先求最大流) *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找 */ const int maxn=1510; const int maxm=600010; const int inf=0x3f3f3f3f; struct Edge { int u,v; int cap,flow; int next; } edge[maxm]; int head[maxn],edgeNum;//需初始化 int n,m,d[maxn],cur[maxn]; int st,ed; bool vis[maxn]; void addSubEdge(int u,int v,int cap,int flow) { edge[edgeNum].u=u; edge[edgeNum].v=v; edge[edgeNum].cap=cap; edge[edgeNum].flow=flow; edge[edgeNum].next=head[u]; head[u]=edgeNum++; cur[u]=head[u]; } void addEdge(int u,int v,int cap) { addSubEdge(u,v,cap,0); addSubEdge(v,u,0,0);//注意加反向0 边 } bool BFS() { queue<int> Q; memset(vis, 0, sizeof(vis)); Q.push(st); d[st]=0; vis[st]=1; while (!Q.empty()) { int u=Q.front(); Q.pop(); for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; int w=edge[i].cap-edge[i].flow; if(w>0 && !vis[v]) { vis[v]=1; Q.push(v); d[v]=d[u]+1; if(v==ed) return 1; } } } return false; } int Aug(int u, int a) { if (u==ed) return a; int aug=0, delta; for(int &i=cur[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; int w=edge[i].cap-edge[i].flow; if (w>0 && d[v]==d[u]+1) { delta = Aug(v, min(a,w)); if (delta) { edge[i].flow += delta; edge[i^1].flow -= delta; aug += delta; if (!(a-=delta)) break; } } } if (!aug) d[u]=-1; return aug; } int Dinic(int NdFlow) { int flow=0; while (BFS()) { memcpy(cur,head,sizeof(int)*(n+1)); flow += Aug(st,inf); /*如果超过指定流量就return 掉*/ if(NdFlow==inf) continue; if(flow > NdFlow) break; } return flow; } /*残余网络*/ void Reduce() { for(int i=0; i<edgeNum; i++) edge[i].cap-=edge[i].flow; } /*清空流量*/ void ClearFlow() { for(int i=0; i<edgeNum; i++) edge[i].flow=0; } /*求最小割*/ vector<int> MinCut() { BFS(); vector<int> ans; for(int u=0; u<n; u++) { if(!vis[u]) continue; for(int i=head[u]; i!=-1; i=edge[i].next) { if(i&1) continue;/*忽略反向边*/ int v=edge[i].v; int w=edge[i].cap; if(!vis[v]&&w>0) ans.push_back(i); } } return ans; } /** *贪心预流:用于分层图Dinic预处理(从0到n-1) *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇),rk[i]=i,level[](分层图的层次) *输出:GreedyPreFlow()(预处理Dinic) */ int in[maxn],out[maxn]; int level[maxn],rk[maxn]; bool cmp(const int &i,const int &j) { return level[i]<level[j]; } void GreedyPreFlow() { memset(in, 0, sizeof (in)); memset(out, 0, sizeof (out)); sort(rk, rk+n, cmp); in[st] = inf; for (int i = 0; i < n; ++i) { int u = rk[i]; for (int j = head[u]; j!=-1; j = edge[j].next) { int v = edge[j].v, w = edge[j].cap-edge[j].flow; if (!(j & 1) && in[u] > out[u]) { int f = min(w, in[u]-out[u]); in[v] += f, out[u] += f; } } } memset(in, 0, sizeof (in)); in[ed] = inf; for (int i = n-1; i >= 0; --i) { int v = rk[i]; for (int j = head[v]; j!=-1; j = edge[j].next) { int u = edge[j].v, w = edge[j^1].cap-edge[j^1].flow; if (j & 1 && out[u] > in[u]) { int f = min(w, min(out[u]-in[u], in[v])); in[u] += f, in[v] -= f; edge[j].flow -= f, edge[j^1].flow += f; } } } } int N,M,L; void init() { memset(head,-1,sizeof(head)); edgeNum=0; } void input() { scanf("%d%d%d",&N,&M,&L); int x=0; int idx=0; st=0,ed=0; for(int i=0; i<N; i++) { scanf("%d",&x); rk[i]=i; level[i]=x; if(x==1) st=i; if(x==L) ed=i; } for(int i=0; i<M; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); u--,v--; addEdge(u,v,w); } n=N; } void solve() { GreedyPreFlow(); ISAP(inf); // cout<<HLPP()<<endl; // cout<<Dinic(inf)<<endl; for(int i=0; i<edgeNum; i+=2) printf("%d\n",edge[i].flow); } void output() { // } int main() { // std::ios_base::sync_with_stdio(false); // freopen("in.cpp","r",stdin); int T; scanf("%d",&T); while(T--) { init(); input(); solve(); output(); } return 0; }
View Code
相关文章推荐
- 4.0多线程用法
- oracle定时器的使用
- 两张图片进行叠加
- Codeforces344_C(数学思维)
- Java 快速开发平台 WB 6.8 发布
- Session的生命周期
- 菲亚特菲跃7座豪华版 引导“翻身仗”
- Google中国2014校园招聘笔试Round A China New Grad Test Problem D. Cross the maze
- boost 安装
- 如何获取input自定义属性
- DEDE图集手工上传图片,加入水印
- 读官网的Java编程规范记录
- DEDE图集手工上传图片,加入水印
- UVA 1456 DP水题
- tomcat使用知识,启动后一闪而过
- rabbitMQ入门
- PKU3522(Slim Span)-求差值最小的生成树
- Windows 7 + IIS 7.5 + DNN 7 Config
- PL/SQL游标详解
- 使用XML提供数据处理效率