codevs1033 蚯蚓的游戏问题 裸最小费用最大流,注意要拆点

因为蚯蚓走过的路径不能重合,所以把每个点拆成两个点,容量赋为1,保证不会走过相同的点,再加超级源点(程序中为1)和一个辅助点(程序中为2)容量赋为k来控制蚯蚓的数量,最后汇集到一个超级汇点上。做一遍最小费用最大流即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 struct charge{
 7     int u,v,cost,c,next;
 8 }f[50000];
 9 int n,m,k,num=2,cnt=0,point[3003],q[50000],pre[3003],dist[3003];
10 bool vis[3003];
11 void insect(int x,int y,int co,int bei)
12 {
13     f[cnt].u=x;f[cnt].v=y;f[cnt].cost=bei;f[cnt].c=co;
14     f[cnt].next=point[x];point[x]=cnt++;
15     f[cnt].u=y;f[cnt].v=x;f[cnt].cost=-bei;f[cnt].c=0;
16     f[cnt].next=point[y];point[y]=cnt++;
17 }
18 bool spfa(int begin,int end)
19 {
20     int mp,a,b,head=0,tail=0;
21     memset(q,0,sizeof(q));
22     memset(pre,0xff,sizeof(pre));
23     memset(dist,0x7f,sizeof(dist));
24     memset(vis,0,sizeof(vis));
25     q[0]=begin; dist[begin]=0; vis[begin]=1;
26     while (head<=tail)
27     {
28         a=q[head];
29         vis[a]=0;
30         mp=point[a];
31         while (mp>=0)
32         {
33             if (f[mp].c>0){
34             b=f[mp].v;
35             if (dist[b]>dist[a]+f[mp].cost)
36             {
37                 dist[b]=dist[a]+f[mp].cost;
38                 pre[b]=mp;
39                 if (!vis[b]){vis[b]=1;tail++;q[tail]=b;}
40             }
41             }
42             mp=f[mp].next;
43         }
44         head++;
45     }
46     return dist[end]!=2139062143;
47 }
48 int MCMF(int begin,int end)
49 {
50     int ans=0,mp,i,flow,flowsum=0;
51     while (spfa(begin,end))
52     {
53         flow=2139062143;
54         for (i=pre[end];i!=-1;i=pre[f[i].u])
55          if (f[i].c<flow) flow=f[i].c;
56         for (i=pre[end];i!=-1;i=pre[f[i].u])
57         {
58             f[i].c-=flow;
59             f[i^1].c+=flow;
60         }
61         ans+=dist[end];
62         flowsum+=flow;
63     }
64     return ans;
65 }
66 int main()
67 {
68     scanf("%d %d %d\n",&n,&m,&k);
69     int i,a,b,c,j,ff;
70     memset(point,0xff,sizeof(point));
71     insect(1,2,k,0);
72     for (i=1;i<=m;++i)
73     {
74         scanf("%d",&c); num+=2;
75         insect(2,num-1,1,0); insect(num-1,num,1,-c);
76     }
77     ff=4;
78     for (i=2;i<=n;++i)
79     {
80         for (j=1;j<=m+i-1;++j)
81         {
82             scanf("%d",&c); num+=2;
83             if (j>1) insect(ff-2,num-1,1,0);
84             if (j<m+i-1) insect(ff,num-1,1,0);
85             insect(num-1,num,1,-c);
86             ff+=2;
87         }
88         ff=num+2-(m+i-1)*2;
89     }
90     for (i=1;i<=m+n-1;++i)
91      insect(num-(m+n-1)*2+i*2,num+1,1,0);
92     num++;
93     printf("%d\n",-1*MCMF(1,num));
94     return 0;
95 }

 

转载于:https://www.cnblogs.com/abclzr/p/5027144.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值