您的位置:首页 > 其它

[ACM]CCF CSP [201412-5]E题 货物调度

2017-10-15 21:07 281 查看
更新下:换了zkw费用流,过掉了所有数据。代码最下面,代码很丑就是了。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

费用流:把每个城市按7天拆成7个点,边就很好连了。(类似猪圈那题)。

只拿到【90分】,估计是我的费用流模板太差了。

据说有个zkw费用流很快,什么时候换下。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
struct EDGE{
int from,to,flow,cap,cost;
EDGE(int u=0,int v=0,int cp=0,int cst=0){from=u;to=v;flow=0;cap=cp;cost=cst;}
};
/*
用法:(1) clearMap
(2) addEdge    节点个数由addEdge自动计算
(3) solve(s,t,&flow,&cost) 计算s->t的最小费用最大流,费用保存在cost中,流保留在flow中
*/
class MCMF{                                  //对费用流进行类似ISAP的优化
#define MCMFINF 0x7fff0000
#define MCMFN   1010
private:
int  s,t;
int  n;                                    //n在添加边时自动维护,节点下标范围[0..n]
int  p[MCMFN];
int  d[MCMFN];
bool inq[MCMFN];
vector<EDGE> e;
vector<int>  g[MCMFN];
bool spfa(int &flow,int &cost);            //是否能找到一条增广路
int  augument(int &flow,int& cost);        //对p中的路径进行增广,流量和费用加在flow和cost中
public:
int  clearMap();
int  addEdge(int u,int v,int cap,int cost);  //添加一条单向边
int  solve(int s,int t,int& flow,int&cost);  //求解s->t的费用流
};
int MCMF::clearMap(){
n=0;
e.clear();
for (int i=0;i<MCMFN;i++)g[i].clear();
return 0;
}
int MCMF::addEdge(int u,int v,int cap,int cost){
if (cap==0) return 0;
n=max(n,u);
n=max(n,v);
e.push_back(EDGE(u,v,cap,cost));
e.push_back(EDGE(v,u,0,-cost));
g[u].push_back(e.size()-2);
g[v].push_back(e.size()-1);
//printf("(%d->%d) cap=%d cost=%d\n",u,v,cap,cost);
return 0;
}
int MCMF::augument(int& flow,int& cost){
int x=t;
int mi_flow=MCMFINF;    //增广路可以通过的流量
int cost2  =0;          //单位流量的cost
while (x!=s){
EDGE ed=e[p[x]];
mi_flow=min(mi_flow,ed.cap-ed.flow);
cost2 +=ed.cost;
x=ed.from;
}
//边的流量增加
x=t;
while(x!=s){
e[p[x]].flow+=mi_flow;
e[p[x]^1].flow-=mi_flow;
x=e[p[x]].from;
}
//
flow+=mi_flow;
cost+=cost2*mi_flow;
return 0;
}
bool MCMF::spfa(int& flow,int& cost){
for (int i=0;i<=n;i++)d[i]=MCMFINF;
memset(inq,0,sizeof(inq));
d[s]=0;
inq[s]=true;
//spfa
queue<int> Q;
Q.push(s);
while (!Q.empty()){
int u=Q.front();Q.pop();
inq[u]=false;
for (int i=0;i<g[u].size();i++){
EDGE ed=e[g[u][i]];
if (ed.cap>ed.flow && d[ed.to]>d[u]+ed.cost){
d[ed.to]=d[u]+ed.cost;
p[ed.to]=g[u][i];
if (!inq[ed.to]){
inq[ed.to]=true;
Q.push(ed.to);
}
}
}
}
//printf("d[%d]=%d\n",t,d[t]);
if (d[t]>=MCMFINF) return false;
augument(flow,cost);
return true;
}
int MCMF::solve(int s,int t,int &flow,int& cost){
flow=cost=0;
this->s=s;
this->t=t;
while (spfa(flow,cost));
return 0;
}
#define N 1010
MCMF mcmf;
int n,m;
int a
[8];
int b
[8];
int w
;
int v
;
struct ED{
int u,v,w;
ED(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
vector<ED>g
;
void read(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
for (int j=1;j<=7;j++)scanf("%d",&a[i][j]);
for (int j=1;j<=7;j++)scanf("%d",&b[i][j]);
scanf("%d%d",&v[i],&w[i]);
}
for (int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[u].push_back(ED(u,v,w));
g[v].push_back(ED(v,u,w));
}
}
#define NODE(city,day) ((city-1)*7+((day)==8?1:(day)))
#define FOR(i,s,t) for (int i=s;i<=t;i++)
void solve(){
//建图
int s=n*7+1;
int t=n*7+2;
mcmf.clearMap();
FOR(city,1,n){
FOR (day,1,7){
//s->city(i,j) a[i][j] cost=0 产生的货物
mcmf.addEdge(s,NODE(city,day),a[city][day],0);
//city(i,j)->t b[i][j] cost=0 消耗的货物
mcmf.addEdge(NODE(city,day),t,b[city][day],0);
}
//货物放到下一天
FOR(day,1,7) mcmf.addEdge(NODE(city,day),NODE(city,day+1),v[city],w[city]);
//货物运输到其他城市
FOR(i,0,g[city].size()-1){
ED e=g[city][i];
FOR(day,1,7){
mcmf.addEdge(NODE(city,day),NODE(e.v,day),0x7fff0000,e.w);
}
}
}
int flow=0,cost=0;
mcmf.solve(s,t,flow,cost);
printf("%d\n",cost);
}
int main(){
read();
solve();
return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////

以下是找了个zkw模板带进入,确实快了。~【100分】

#include <cstdio>
#include <cstring>
#include<vector>
#include <iostream>
using namespace std;
const int maxint=~0U>>1;

/*
用法:n节点个数。求解节点0到节点n的费用流
(1)设置n
(2)addEdge
(3)solve()
*/
#define N 1000
#define M 50000
int n,m,pi1,cost=0;
bool v
;
struct etype
{
int t,c,u;
etype *next,*pair;
etype(){}
etype(int t_,int c_,int u_,etype* next_):
t(t_),c(c_),u(u_),next(next_){}
//void* operator new(unsigned,void* p){return p;}
} *e[M];

etype *Pe=new etype[M];

int aug(int no,int m)
{
if(no==n)return cost+=pi1*m,m;
v[no]=true;
int l=m;
for(etype *i=e[no];i;i=i->next)
if(i->u && !i->c && !v[i->t])
{
int d=aug(i->t,l<i->u?l:i->u);
i->u-=d,i->pair->u+=d,l-=d;
if(!l)return m;
}
return m-l;
}

bool modlabel()
{
int d=maxint;
for(int i=1;i<=n;++i)if(v[i])
for(etype *j=e[i];j;j=j->next)
if(j->u && !v[j->t] && j->c<d)d=j->c;
if(d==maxint)return false;
for(int i=1;i<=n;++i)if(v[i])
for(etype *j=e[i];j;j=j->next)
j->c-=d,j->pair->c+=d;
pi1 += d;
return true;
}
int solve(){
cost=0;
do do memset(v,0,sizeof(v));
while(aug(1,maxint));
while(modlabel());
return cost;
}
void addEdge(int s,int t,int u,int c){
e[s]=new(Pe++)etype(t, c,u,e[s]);
e[t]=new(Pe++)etype(s,-c,0,e[t]);
e[s]->pair=e[t];
e[t]->pair=e[s];

}
struct ED{
int u,v,w;
ED(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
struct PROBLEM{
int n,m;
int a
[8];
int b
[8];
int w
;
int v
;
vector<ED>g
;
void read(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
for (int j=1;j<=7;j++)scanf("%d",&a[i][j]);
for (int j=1;j<=7;j++)scanf("%d",&b[i][j]);
scanf("%d%d",&v[i],&w[i]);
}
for (int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[u].push_back(ED(u,v,w));
g[v].push_back(ED(v,u,w));
}
}

#define NODE(city,day) (((city-1)*7+((day)==8?1:(day)))+1)
#define FOR(i,s,t) for (int i=s;i<=t;i++)
void solve(){
//建图
int s=1;
int t=n*7+2;
FOR(city,1,n){
FOR (day,1,7){
//s->city(i,j) a[i][j] cost=0 产生的货物
addEdge(s,NODE(city,day),a[city][day],0);
//city(i,j)->t b[i][j] cost=0 消耗的货物
addEdge(NODE(city,day),t,b[city][day],0);
}
//货物放到下一天
FOR(day,1,7) addEdge(NODE(city,day),NODE(city,day+1),v[city],w[city]);
//货物运输到其他城市
FOR(i,0,g[city].size()-1){
ED e=g[city][i];
FOR(day,1,7){
addEdge(NODE(city,day),NODE(e.v,day),0x7fff0000,e.w);
}
}
}
}
}problem;
int main()
{
problem.read();
problem.solve();
n=problem.n*7+2;
printf("%d\n",solve());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: