首页 > 代码库 > BZOJ2055: 80人环游世界
BZOJ2055: 80人环游世界
题解:
总算A掉了,各种蛋疼。。。
int main(){ freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read();s=0;t=2*n+m+1;ss=t+1;tt=t+2;sss=tt+1; insert(s,sss,0,m,0); for1(i,n)insert(sss,i,0,inf,0); for1(i,n){int x=read();insert(i,i+n,x,x,0);} for1(i,n)for2(j,i+1,n){int x=read();if(x!=-1)insert(i+n,j,0,inf,x);} for1(i,n)insert(i+n,t,0,inf,0); insert(t,s,0,inf,0); mcf(); printf("%d\n",mincost); return 0;}
s是附加源,sss是真正的源,t是真正的汇。这样构图就好了,但我们还有下界限制,那再来个ss,tt。。。居然还是费用流。。。然后这题就做完了
因为我们只需要最小费用,所以我们只需求出可行流&最小费用即可。
关于下界的处理我直接写在insert函数里。。。导致慢成翔。。。
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set>10 #include<queue>11 #include<string>12 #define inf 100000000013 #define maxn 20000014 #define maxm 20000015 #define eps 1e-1016 #define ll long long17 #define pa pair<int,int>18 #define for0(i,n) for(int i=0;i<=(n);i++)19 #define for1(i,n) for(int i=1;i<=(n);i++)20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)22 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)23 #define mod 100000000724 using namespace std;25 inline int read()26 {27 int x=0,f=1;char ch=getchar();28 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}29 while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();}30 return x*f;31 }32 int n,m,k,mincost,tot=1,s,t,ss,tt,sss,head[maxn],d[maxn],from[2*maxm];33 bool v[maxn];34 queue<int>q;35 struct edge{int from,go,next,v,c;}e[2*maxm];36 void ins(int x,int y,int v,int c)37 {38 e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;39 e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;40 }41 void insert(int x,int y,int l,int r,int c)42 {43 ins(ss,y,l,c);ins(x,tt,l,0);ins(x,y,r-l,c);44 }45 bool spfa()46 {47 for (int i=0;i<=sss;i++){v[i]=0;d[i]=inf;}48 q.push(ss);d[ss]=0;v[ss]=1;49 while(!q.empty())50 {51 int x=q.front();q.pop();v[x]=0;52 for (int i=head[x],y;i;i=e[i].next)53 if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])54 {55 d[y]=d[x]+e[i].c;from[y]=i;56 if(!v[y]){v[y]=1;q.push(y);}57 }58 }59 return d[tt]!=inf;60 }61 void mcf()62 {63 mincost=0;64 while(spfa())65 {66 int tmp=inf;67 for(int i=from[tt];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);68 mincost+=d[tt]*tmp;69 for(int i=from[tt];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}70 }71 }72 int main()73 {74 freopen("input.txt","r",stdin);75 freopen("output.txt","w",stdout);76 n=read();m=read();s=0;t=2*n+m+1;ss=t+1;tt=t+2;sss=tt+1;77 insert(s,sss,0,m,0);78 for1(i,n)insert(sss,i,0,inf,0);79 for1(i,n){int x=read();insert(i,i+n,x,x,0);}80 for1(i,n)for2(j,i+1,n){int x=read();if(x!=-1)insert(i+n,j,0,inf,x);}81 for1(i,n)insert(i+n,t,0,inf,0);82 insert(t,s,0,inf,0);83 mcf();84 printf("%d\n",mincost);85 return 0;86 }
UPD:把边合并了之后用时成了1/4
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set>10 #include<queue>11 #include<string>12 #define inf 100000000013 #define maxn 20000014 #define maxm 20000015 #define eps 1e-1016 #define ll long long17 #define pa pair<int,int>18 #define for0(i,n) for(int i=0;i<=(n);i++)19 #define for1(i,n) for(int i=1;i<=(n);i++)20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)22 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)23 #define mod 100000000724 using namespace std;25 inline int read()26 {27 int x=0,f=1;char ch=getchar();28 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}29 while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();}30 return x*f;31 }32 int n,m,k,mincost,tot=1,s,t,ss,tt,sss,head[maxn],d[maxn],from[2*maxm],in[maxn];33 bool v[maxn];34 queue<int>q;35 struct edge{int from,go,next,v,c;}e[2*maxm];36 void ins(int x,int y,int v,int c)37 {38 e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;39 e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;40 }41 void insert(int x,int y,int l,int r,int c)42 {43 in[y]+=l;44 in[x]-=l;45 ins(x,y,r-l,c);46 }47 void build()48 {49 for0(i,sss)if(in[i]>0)ins(ss,i,in[i],0);50 else if(in[i]<0)ins(i,tt,-in[i],0);51 }52 bool spfa()53 {54 for (int i=0;i<=sss;i++){v[i]=0;d[i]=inf;}55 q.push(ss);d[ss]=0;v[ss]=1;56 while(!q.empty())57 {58 int x=q.front();q.pop();v[x]=0;59 for (int i=head[x],y;i;i=e[i].next)60 if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])61 {62 d[y]=d[x]+e[i].c;from[y]=i;63 if(!v[y]){v[y]=1;q.push(y);}64 }65 }66 return d[tt]!=inf;67 }68 void mcf()69 {70 mincost=0;71 while(spfa())72 {73 int tmp=inf;74 for(int i=from[tt];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);75 mincost+=d[tt]*tmp;76 for(int i=from[tt];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}77 }78 }79 int main()80 {81 freopen("input.txt","r",stdin);82 freopen("output.txt","w",stdout);83 n=read();m=read();s=0;t=2*n+m+1;ss=t+1;tt=t+2;sss=tt+1;84 insert(s,sss,0,m,0);85 for1(i,n)insert(sss,i,0,inf,0);86 for1(i,n){int x=read();insert(i,i+n,x,x,0);}87 for1(i,n)for2(j,i+1,n){int x=read();if(x!=-1)insert(i+n,j,0,inf,x);}88 for1(i,n)insert(i+n,t,0,inf,0);89 insert(t,s,0,inf,0);90 build();91 mcf();92 printf("%d\n",mincost);93 return 0;94 }
2055: 80人环游世界
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 116 Solved: 75
[Submit][Status]
Description
Input
第一行两个正整数N,M。第二行有N个不大于M正整数,分别表示V1,V2......VN。接下来有N ¡ 1行。第i行有N ¡ i个整数,该行的第j个数表示从第i个国家到第i + j个国家的机票费(如果该值等于¡1则表示这两个国家间没有通航)。
Output
在第一行输出最少的总费用。
Sample Input
6 3
2 1 3 1 2 1
2 6 8 5 0
8 2 4 1
6 1 0
4 -1
4
2 1 3 1 2 1
2 6 8 5 0
8 2 4 1
6 1 0
4 -1
4
Sample Output
27
HINT
1<= N < =100 1<= M <= 79
BZOJ2055: 80人环游世界
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。