[网络流24题 #18]分配问题
2014-01-21 13:40
381 查看
这个题目写到了手残的境界,十分感动,不必多说。
首先是加反向边时下标没有反过来,然后是基于费用的最短(最长)路每次写成基于弧的容量……
最后就是临时数组开小了,导致开始评测只有11分,搞得我真是很无语。
看了wjk大神在很久很久以前的代码,发现他的增广是递归式的(在这一点上我比他有优势,非递归)
最后发现wjk大神代码没有用临时数组,着实把我震撼了,后来才发现他原来用正向边和反向边的关系直接还原容量。这个我的代码没有改过来,不过评测时还是比他快3ms,(*^__^*) ……
下面上我的代码(至于wjk大神的,点这里)#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define clean(x,y) memset(x,y,sizeof(x))
#define compare(CurP,AnoP,way) way? d[AnoP]<d[CurP]+a[i].cost:d[AnoP]>d[CurP]+a[i].cost
#define loop(i,u) for(i=p[T][0],u=p[T][1];i!=-1;i=p[u][0],u=p[u][1])
#define add(x) Q.push(x),v[x]=1
#define del(x) x=Q.front(),Q.pop(),v[x]=0
#define MaxN 110
using namespace std;
const int lim[2]={~0U>>2,-(~0U>>2)};
int n,tot,S,T; /*source & sink*/
int head[MaxN],d[MaxN],p[MaxN][2]; /*Augment Path*/
int temp[2*MaxN*MaxN]; /*Temp Cap*/
struct edge
{
int v,cap,cost,next;
edge(int x,int y,int c,int b):v(y),cap(c),cost(b)
{
next=head[x];
head[x]=tot++;
}
};
vector<edge> a;
bool v[MaxN]; /*If in Queue*/
inline void AddEdge(const int &x,const int &y,const int &cap,const int &cost)
{
a.push_back(edge(x,y,cap,cost));
a.push_back(edge(y,x,0,-cost));
}
inline void init()
{
int w;
cin>>n;
clean(head,-1);
for(int i=1;i<=n;i++)
for(int j=n+1;j<=2*n;j++)
scanf("%d",&w),
AddEdge(i,j,lim[0],w);
S=2*n+1,T=2*n+2;
for(int i=1;i<=n;i++)
AddEdge(S,i,1,0);
for(int j=n+1;j<S;j++)
AddEdge(j,T,1,0);
n=T;
}
inline bool spfa(bool cmp) /* cmp=0:shortest cmp=1:longest */
{
queue<int> Q;
for(int i=1;i<=T;i++)
d[i]=lim[cmp];
d[S]=0;
add(S);
clean(v,0);
clean(p,-1);
int x,y;
while(!Q.empty())
{
del(x);
for(int i=head[x];i!=-1;i=a[i].next)
{
y=a[i].v;
if(temp[i]>0&&(compare(x,y,cmp)))
{
d[y]=d[x]+a[i].cost;
p[y][0]=i,p[y][1]=x;
if(!v[y]) add(y);
}
}
}
return d[T]!=lim[cmp];
}
inline void work()
{
int cost,u,i,flow;
for(int way=0;way<2;way++)
{
cost=0;
for(i=0;i<tot;i++) temp[i]=a[i].cap;
while(spfa(way))
{
flow=lim[0];
loop(i,u)
if(flow>temp[i])
flow=temp[i];
loop(i,u)
{
temp[i]-=flow;
temp[i^1]+=flow;
}
cost+=d[T]*flow;
}
cout<<cost<<endl;
}
}
int main()
{
init();
work();
return 0;
}
首先是加反向边时下标没有反过来,然后是基于费用的最短(最长)路每次写成基于弧的容量……
最后就是临时数组开小了,导致开始评测只有11分,搞得我真是很无语。
看了wjk大神在很久很久以前的代码,发现他的增广是递归式的(在这一点上我比他有优势,非递归)
最后发现wjk大神代码没有用临时数组,着实把我震撼了,后来才发现他原来用正向边和反向边的关系直接还原容量。这个我的代码没有改过来,不过评测时还是比他快3ms,(*^__^*) ……
下面上我的代码(至于wjk大神的,点这里)#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define clean(x,y) memset(x,y,sizeof(x))
#define compare(CurP,AnoP,way) way? d[AnoP]<d[CurP]+a[i].cost:d[AnoP]>d[CurP]+a[i].cost
#define loop(i,u) for(i=p[T][0],u=p[T][1];i!=-1;i=p[u][0],u=p[u][1])
#define add(x) Q.push(x),v[x]=1
#define del(x) x=Q.front(),Q.pop(),v[x]=0
#define MaxN 110
using namespace std;
const int lim[2]={~0U>>2,-(~0U>>2)};
int n,tot,S,T; /*source & sink*/
int head[MaxN],d[MaxN],p[MaxN][2]; /*Augment Path*/
int temp[2*MaxN*MaxN]; /*Temp Cap*/
struct edge
{
int v,cap,cost,next;
edge(int x,int y,int c,int b):v(y),cap(c),cost(b)
{
next=head[x];
head[x]=tot++;
}
};
vector<edge> a;
bool v[MaxN]; /*If in Queue*/
inline void AddEdge(const int &x,const int &y,const int &cap,const int &cost)
{
a.push_back(edge(x,y,cap,cost));
a.push_back(edge(y,x,0,-cost));
}
inline void init()
{
int w;
cin>>n;
clean(head,-1);
for(int i=1;i<=n;i++)
for(int j=n+1;j<=2*n;j++)
scanf("%d",&w),
AddEdge(i,j,lim[0],w);
S=2*n+1,T=2*n+2;
for(int i=1;i<=n;i++)
AddEdge(S,i,1,0);
for(int j=n+1;j<S;j++)
AddEdge(j,T,1,0);
n=T;
}
inline bool spfa(bool cmp) /* cmp=0:shortest cmp=1:longest */
{
queue<int> Q;
for(int i=1;i<=T;i++)
d[i]=lim[cmp];
d[S]=0;
add(S);
clean(v,0);
clean(p,-1);
int x,y;
while(!Q.empty())
{
del(x);
for(int i=head[x];i!=-1;i=a[i].next)
{
y=a[i].v;
if(temp[i]>0&&(compare(x,y,cmp)))
{
d[y]=d[x]+a[i].cost;
p[y][0]=i,p[y][1]=x;
if(!v[y]) add(y);
}
}
}
return d[T]!=lim[cmp];
}
inline void work()
{
int cost,u,i,flow;
for(int way=0;way<2;way++)
{
cost=0;
for(i=0;i<tot;i++) temp[i]=a[i].cap;
while(spfa(way))
{
flow=lim[0];
loop(i,u)
if(flow>temp[i])
flow=temp[i];
loop(i,u)
{
temp[i]-=flow;
temp[i^1]+=flow;
}
cost+=d[T]*flow;
}
cout<<cost<<endl;
}
}
int main()
{
init();
work();
return 0;
}
相关文章推荐
- [网络流24题] 18 分配问题(二分图最佳匹配,最小费用最大流)
- 分配问题[网络流24题之18]
- [网络流24题 #18]分配问题
- 【网络流24题-18】分配问题(BSOI2558)
- 【网络流24题】分配问题
- 【网络流24题】分配问题 最小最大费用最大流
- 网络流24题 -No.18 分配问题
- LOJ6122 「网络流 24 题 - 18」 航空路线问题 最长不相交路径 坠大费用坠大流
- 【网络流24题】No.18 分配问题 (二分图最佳匹配 费用流|KM)
- [网络流24题]分配问题
- [网络流24题][CODEVS1915]分配问题(网络流)
- Luogu P4014 「 网络流 24 题 」分配问题
- loj6012「网络流 24 题」分配问题
- [网络流24题] 分配问题
- loj6012「网络流 24 题」分配问题(费用流)
- 「网络流 24 题」分配问题
- cogs 740. [网络流24题] 分配问题
- Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)
- 网络流24题18. 分配问题
- 【网络流24题】分配问题