bzoj2055: 80人环游世界(可行流)

Posted bztminamoto

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2055: 80人环游世界(可行流)相关的知识,希望对你有一定的参考价值。

传送门

 

表示完全看不懂最小费用可行流……

据某大佬说

我们考虑拆点,然后进行如下连边

$s$向$a_i$连边,权值$0$,容量$[0,m]$

$a_i$向$a_i‘$连边,权值$0$容量$[v_i,v_i]$

如果存在边$(i,j)$,则连边$a_i‘->a_i$,权值为$w_{i,j}$,容量$[0,m]$

$a_i‘$向$t$连边,权值$0$,容量$[0,m]$

$t$向$t‘$连边,权值$0$容量$[0,m]$

然后跑个最小费用可行流

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 9 char buf[1<<21],*p1=buf,*p2=buf;
10 inline int read(){
11     #define num ch-‘0‘
12     char ch;bool flag=0;int res;
13     while(!isdigit(ch=getc()))
14     (ch==-)&&(flag=true);
15     for(res=num;isdigit(ch=getc());res=res*10+num);
16     (flag)&&(res=-res);
17     #undef num
18     return res;
19 }
20 const int N=505,M=500005;
21 int head[N],Next[M],ver[M],edge[M],flow[M],tot=1;
22 inline void add(int u,int v,int e,int f){
23     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,flow[tot]=f;
24     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=-e,flow[tot]=0;
25 }
26 int dis[N],vis[N],cur[N],S,T,ans,s,t,kt,n,m;
27 queue<int> q;
28 bool spfa(){
29     memset(dis,-1,sizeof(dis));
30     memset(vis,0,sizeof(vis));
31     memcpy(cur,head,sizeof(head));
32     q.push(T),dis[T]=0,vis[T]=1;
33     while(!q.empty()){
34         int u=q.front();q.pop();vis[u]=0;
35         for(int i=head[u];i;i=Next[i])
36         if(flow[i^1]){
37             int v=ver[i],e=edge[i];
38             if(dis[v]<0||dis[v]>dis[u]-e){
39                 dis[v]=dis[u]-e;
40                 if(!vis[v]) vis[v]=1,q.push(v);
41             }
42         }
43     }
44     return ~dis[S];
45 }
46 int dfs(int u,int limit){
47     if(!limit||u==T) return limit;
48     int fl=0,f;vis[u]=1;
49     for(int i=cur[u];i;cur[u]=i=Next[i]){
50         int v=ver[i];
51         if(dis[v]==dis[u]-edge[i]&&!vis[v]&&(f=dfs(v,min(limit,flow[i])))){
52             fl+=f,limit-=f;
53             ans+=f*edge[i];
54             flow[i]-=f,flow[i^1]+=f;
55             if(!limit) break;
56         }
57     }
58     vis[u]=0;
59     return fl;
60 }
61 void zkw(){
62     while(spfa()) dfs(S,inf);
63 }
64 int main(){
65     //freopen("testdata.in","r",stdin);
66     n=read(),m=read(),s=2*n+1,t=s+1,kt=t+1,S=kt+1,T=S+1;
67     for(int i=1;i<=n;++i){
68         int x=read();
69         add(S,i+n,0,x),add(i,T,0,x),
70         add(s,i,0,m),add(i+n,t,0,m);
71     }
72     add(t,kt,0,m),add(kt,s,0,inf);
73     for(int i=1;i<=n;++i)
74     for(int j=i+1;j<=n;++j){
75         int x=read();
76         if(~x) add(n+i,j,x,inf);
77     }
78     zkw();
79     printf("%d
",ans);
80     return 0;
81 }

 

以上是关于bzoj2055: 80人环游世界(可行流)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2055 80人环游世界

bzoj千题计划159:bzoj2055: 80人环游世界(上下界费用流)

bzoj2055 80人环游世界

[bzoj2055] 80人环游世界

bzoj205580人环游世界 有上下界费用流

P4553 80人环游世界 上下界费用流