您的位置:首页 > 其它

ZOJ 1638 Greedy Island

2016-03-04 15:14 337 查看
还是论文题

话说照我这个速度要刷到猴年马月(他喵的已经是猴年了QAQ)

这题模型挺好想得,很直观的最大费用最大流,唯一要想一下的就是优化了。

当然还有个很坑爹的地方就是spfa可以求2维费用流(两个关键字)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1e9;
struct Edge{int from,to,next,v,c,c1;}e[200005];
int head[310],cnt;
void ins(int u,int v,int w,int c,int c1){
e[++cnt]=(Edge){u,v,head[u],w,c,c1};head[u]=cnt;
}
void insert(int u,int v,int w,int c,int c1){
ins(u,v,w,c,c1);ins(v,u,0,-c,-c1);
}
int d[310],from[310],h[310];
bool inq[310];
bool spfa(int s,int t,int &cost,int &sum){
memset(d,-0x3f,sizeof(d));
memset(h,-0x3f,sizeof(h));
d[s]=0;h[s]=0;queue<int>q;q.push(s);
while(!q.empty()){
int u=q.front();q.pop();inq[u]=0;
for(int i=head[u];i;i=e[i].next)
if(e[i].v&&(d[e[i].to]<d[u]+e[i].c||(d[e[i].to]==d[u]+e[i].c&&h[e[i].to]<h[u]+e[i].c1))){
d[e[i].to]=d[u]+e[i].c;
h[e[i].to]=h[u]+e[i].c1;
from[e[i].to]=i;
if(!inq[e[i].to])inq[e[i].to]=1,q.push(e[i].to);
}
}
if(d[t]<0)return false;
int x=inf;
for(int i=from[t];i;i=from[e[i].from])x=min(x,e[i].v);
for(int i=from[t];i;i=from[e[i].from])
e[i].v-=x,e[i^1].v+=x;
cost+=x*d[t];sum+=x*h[t];
return true;
}
int ans,sum;
void mcf(int s,int t){while(spfa(s,t,ans,sum));}
int A,B,C,a[100105],b[100105],c[100105],rk[100105];
bool cmpa(int i,int j){
if(a[i]==a[j])return a[i]+b[i]+c[i]>a[j]+b[j]+c[j];
return a[i]>a[j];
}
bool cmpb(int i,int j){
if(b[i]==b[j])return a[i]+b[i]+c[i]>a[j]+b[j]+c[j];
return b[i]>b[j];
}
bool cmpc(int i,int j){
if(c[i]==c[j])return a[i]+b[i]+c[i]>a[j]+b[j]+c[j];
return c[i]>c[j];
}
int id[310];
int main(){
//freopen("a.in","r",stdin);
int cas;scanf("%d",&cas);
while(cas--){
int n;scanf("%d",&n);
scanf("%d%d%d",&A,&B,&C);
ans=sum=0;
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);

for(int i=1;i<=n;i++)rk[i]=i;
sort(rk+1,rk+1+n,cmpa);
for(int i=1;i<=A+B+C;i++)id[i]=rk[i];

for(int i=1;i<=n;i++)rk[i]=i;
sort(rk+1,rk+1+n,cmpb);
for(int i=1;i<=A+B+C;i++)id[i+A+B+C]=rk[i];

for(int i=1;i<=n;i++)rk[i]=i;
sort(rk+1,rk+1+n,cmpc);
for(int i=1;i<=A+B+C;i++)id[i+2*(A+B+C)]=rk[i];

int m=3*(A+B+C);
sort(id+1,id+1+m);m=unique(id+1,id+1+m)-id-1;
memset(head,0,sizeof(head));cnt=1;
int S=0,p1=m+1,p2=m+2,p3=m+3,T=m+4;
insert(S,p1,A,0,0);insert(S,p2,B,0,0);insert(S,p3,C,0,0);
for(int i=1;i<=m;i++){
insert(p1,i,1,a[id[i]],a[id[i]]+b[id[i]]+c[id[i]]);
insert(p2,i,1,b[id[i]],a[id[i]]+b[id[i]]+c[id[i]]);
insert(p3,i,1,c[id[i]],a[id[i]]+b[id[i]]+c[id[i]]);
insert(i,T,1,0,0);
}
mcf(S,T);
printf("%d %d\n",ans,sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: