您的位置:首页 > 其它

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和贪心预流模板~

//#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: