poj 1459
2010-07-16 17:51
183 查看
这道题是典型的最大流的问题,而我也只会EK算法,其他的不太懂,但是EK算法用不好就会超时。
开始用STL输入用cin,但是TLE,改成数组和合scanf以后还是超时,后来我发现,一个浪费时间的df,下面我已经注释。
其实EK基本上可以满足你做网络流。
#include<iostream>
#include<cstdio>
using namespace std;
#define MIN(a,b) a<b?a:b
#define M 110
int start,end;
int n,np,nc,m;
int net[M][M];
int path[M*M];
int add;
void init();
int bfs();
void EK();
void init()//初始化,增加一个源点和汇点共n+2个点
{
int i;
int u,v,w;
memset(net,0,sizeof(net));
for(i=0;i<m;i++)
{
while(getchar()!='(');
scanf("%d,%d)%d",&u,&v,&w);
net[u+1][v+1]=w;
}
for(i=0;i<np;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&w);
net[0][u+1]=w;
}
for(i=0;i<nc;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&w);
net[u+1][n+1]=w;
}
start=0;
end=n+1;
return;
}
int bfs()
{
int mark=0;
int i;
memset(path,-1,sizeof(path));
int q[1000];
int t,s;
t=0,s=-1;
//q.push(start);
q[t]=start;
path[start]=-2;
while(s!=t)//找一条到汇点的通路
{
s++;
int cur=q[s];
for(int i=0;i<=n+1;i++)
{
if(path[i]==-1&&net[cur][i]>0)
{
q[++t]=i;
path[i]=cur;
if(i==n+1)//一定记住一定要到汇点才算是一条路,否则不是,这个事你TLE的关键,瓶颈。
{
mark=1;
goto m1;
}
}
}
}
m1:if(mark)
{
if(path[end]==-1)
return -1;
int min_flow=INT_MAX;
int next=end;
int pre=path[next];
while(next!=start)//求得从源点到会点最小流量
{
min_flow=MIN(min_flow,net[pre][next]);
next=pre;
pre=path[next];
}
add=min_flow;
}
return mark;
}
void EK()
{
int max_flow=0;
while(bfs())
{
max_flow+=add;
int next=end;
int pre=path[next];
while(next!=start)//更新
{
net[pre][next]-=add;
net[next][pre]+=add;
next=pre;
pre=path[next];
}
}
cout<<max_flow<<endl;
return;
}
int main()
{
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
init();
EK();
}
return 0;
}
//转一篇重标记法的报告,听说这个效率很高。
#include<iostream>
#include<cstdlib>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
const int INF=1000000000;
const int MAXN=105;
int n,np,nc,m,s,t;
int a[MAXN], p[MAXN], cap[MAXN][MAXN], flow[MAXN][MAXN]; //a[i]存储的是源点s到节点i的路径上的最小残留量,因为a[i]总是整数.于是可用它来替代标记数组
int main()
{
int i,u,v,w,ans;
queue<int>q;
char ss[30];
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
memset(flow,0,sizeof(flow));
memset(cap,0,sizeof(cap));
ans=0;
s=n; //源点
t=n+1; //汇点
for(i=1;i<=m;i++) //输入m条边的信息
{
scanf("%s",ss);
sscanf(ss,"(%d,%d)%d",&u,&v,&w); //这里用sccanf来实现数字分离
cap[u][v]=w;
}
for(i=1;i<=np;i++) //输入np个发电厂的信息
{
scanf("%s",ss);
sscanf(ss,"(%d)%d",&v,&w);
cap[s][v]=w; //将源点和该发电厂连接连接,并置该边的权值为该发电厂的容量
}
for(i=1;i<=nc;i++) //输入nc个用户的信息
{
scanf("%s",ss);
sscanf(ss,"(%d)%d",&u,&w);
cap[u][t]=w; //将该用户和汇点连接,并将该边的权值置为该用户的容量
}
while(1)
{
memset(a,0,sizeof(a));
a[s]=INF;
q.push(s);
while(!q.empty()) //BFS找增广路
{
u=q.front();
q.pop();
for(v=0;v<=t;v++)
if(!a[v]&&cap[u][v]>flow[u][v]) //这里用a[v]来替代了用来标记访问的数组
{
p[v]=u; //记录v的父亲,并加入FIFO队列
q.push(v);
a[v]=min(a[u],cap[u][v]-flow[u][v]); //路径上的最小残量
}
}
if(a[t]==0) //找不到,则当前流已经是最大流
break;
for(u=t;u!=s;u=p[u]) //从汇点往回走
{
flow[p[u]][u]+=a[t]; //更新正向流量
flow[u][p[u]]-=a[t]; //更新反向流量
}
ans+=a[t]; //更新净流量
}
printf("%d/n",ans);
}
system("pause");
return 0;
}
开始用STL输入用cin,但是TLE,改成数组和合scanf以后还是超时,后来我发现,一个浪费时间的df,下面我已经注释。
其实EK基本上可以满足你做网络流。
#include<iostream>
#include<cstdio>
using namespace std;
#define MIN(a,b) a<b?a:b
#define M 110
int start,end;
int n,np,nc,m;
int net[M][M];
int path[M*M];
int add;
void init();
int bfs();
void EK();
void init()//初始化,增加一个源点和汇点共n+2个点
{
int i;
int u,v,w;
memset(net,0,sizeof(net));
for(i=0;i<m;i++)
{
while(getchar()!='(');
scanf("%d,%d)%d",&u,&v,&w);
net[u+1][v+1]=w;
}
for(i=0;i<np;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&w);
net[0][u+1]=w;
}
for(i=0;i<nc;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&w);
net[u+1][n+1]=w;
}
start=0;
end=n+1;
return;
}
int bfs()
{
int mark=0;
int i;
memset(path,-1,sizeof(path));
int q[1000];
int t,s;
t=0,s=-1;
//q.push(start);
q[t]=start;
path[start]=-2;
while(s!=t)//找一条到汇点的通路
{
s++;
int cur=q[s];
for(int i=0;i<=n+1;i++)
{
if(path[i]==-1&&net[cur][i]>0)
{
q[++t]=i;
path[i]=cur;
if(i==n+1)//一定记住一定要到汇点才算是一条路,否则不是,这个事你TLE的关键,瓶颈。
{
mark=1;
goto m1;
}
}
}
}
m1:if(mark)
{
if(path[end]==-1)
return -1;
int min_flow=INT_MAX;
int next=end;
int pre=path[next];
while(next!=start)//求得从源点到会点最小流量
{
min_flow=MIN(min_flow,net[pre][next]);
next=pre;
pre=path[next];
}
add=min_flow;
}
return mark;
}
void EK()
{
int max_flow=0;
while(bfs())
{
max_flow+=add;
int next=end;
int pre=path[next];
while(next!=start)//更新
{
net[pre][next]-=add;
net[next][pre]+=add;
next=pre;
pre=path[next];
}
}
cout<<max_flow<<endl;
return;
}
int main()
{
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
init();
EK();
}
return 0;
}
//转一篇重标记法的报告,听说这个效率很高。
#include<iostream>
#include<cstdlib>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
const int INF=1000000000;
const int MAXN=105;
int n,np,nc,m,s,t;
int a[MAXN], p[MAXN], cap[MAXN][MAXN], flow[MAXN][MAXN]; //a[i]存储的是源点s到节点i的路径上的最小残留量,因为a[i]总是整数.于是可用它来替代标记数组
int main()
{
int i,u,v,w,ans;
queue<int>q;
char ss[30];
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
memset(flow,0,sizeof(flow));
memset(cap,0,sizeof(cap));
ans=0;
s=n; //源点
t=n+1; //汇点
for(i=1;i<=m;i++) //输入m条边的信息
{
scanf("%s",ss);
sscanf(ss,"(%d,%d)%d",&u,&v,&w); //这里用sccanf来实现数字分离
cap[u][v]=w;
}
for(i=1;i<=np;i++) //输入np个发电厂的信息
{
scanf("%s",ss);
sscanf(ss,"(%d)%d",&v,&w);
cap[s][v]=w; //将源点和该发电厂连接连接,并置该边的权值为该发电厂的容量
}
for(i=1;i<=nc;i++) //输入nc个用户的信息
{
scanf("%s",ss);
sscanf(ss,"(%d)%d",&u,&w);
cap[u][t]=w; //将该用户和汇点连接,并将该边的权值置为该用户的容量
}
while(1)
{
memset(a,0,sizeof(a));
a[s]=INF;
q.push(s);
while(!q.empty()) //BFS找增广路
{
u=q.front();
q.pop();
for(v=0;v<=t;v++)
if(!a[v]&&cap[u][v]>flow[u][v]) //这里用a[v]来替代了用来标记访问的数组
{
p[v]=u; //记录v的父亲,并加入FIFO队列
q.push(v);
a[v]=min(a[u],cap[u][v]-flow[u][v]); //路径上的最小残量
}
}
if(a[t]==0) //找不到,则当前流已经是最大流
break;
for(u=t;u!=s;u=p[u]) //从汇点往回走
{
flow[p[u]][u]+=a[t]; //更新正向流量
flow[u][p[u]]-=a[t]; //更新反向流量
}
ans+=a[t]; //更新净流量
}
printf("%d/n",ans);
}
system("pause");
return 0;
}
相关文章推荐
- POJ1459
- POJ 1459 Power Network
- poj 1459 Power Network(最大流)
- POJ 1459 Power Network 多源点多汇点+最大流(EK算法)
- POJ 1459 Power Network
- POJ 1459 网络流算法(EK)
- POJ 1459 Power Network
- POJ - 1459 Power Network(网络流-最大流)
- poj 1459 最大流
- POJ 1459 Power Network 经典网络流构图问题 最大流,EK算法、Dinic算法、ISAP算法
- POJ 1459
- poj1459最大流
- POJ 1459 Power Network(网络最大流,dinic算法模板题)
- poj 1459 最大流(Dinic)
- 【网络流】 POJ 1459 Power Network
- poj1459最高标号预流推进算法解题报告
- POJ 1459 Power Network【最大流基础题 EK 算法】
- poj1459网络流之多源点最大流
- POJ:1459 Power Network
- POJ 1459 Power Network(最大流入门)