说明:S,表示超级原点,T表示超级汇点,<i,j,k(,l)>表示i到j建边,流量为k(,费用为l),某些题由于没有及时纠正码风,板子的常数较大。。。。。

 bzoj4177 Mike的农场

题解:考虑割,养牛的收益为a[i],养羊b[i],对于每个位置<S,i,ai> <i,T,bi>分别表示养牛和养羊,对于两个互相影响的位置<i,j,ci>;做最小割可以满足前两个限制 ;第三个限制,如果全养牛可以获得d,新建一个点x,考虑要求全养牛的位置为集合为s,<S,x,d> , <x,si,inf> , 当si中有一个没有被割,那么<S,x,d>一定被割,养羊同理对T建,设最小割为C,ans = $( \sum (a[i]+b[i]) + \sum c[i]  ) – C $         

 1 #include<bits/stdc++.h>
 2 #define inf 0x3f3f3f3f
 3 using namespace std;
 4 const int N=10010,M=80010;
 5 int S,T,n,m,k,o,hd[N],cur[N],vis[N],d[N];
 6 struct Edge{int v,nt,c,f;}E[M<<1];
 7 char gc(){
 8     static char*p1,*p2,s[1000000];
 9     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
10     return(p1==p2)?EOF:*p1++; 
11 }
12 int rd(){
13     int x=0; char c=gc();
14     while(c<'0'||c>'9')c=gc();
15     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
16     return x;
17 }
18 void adde(int u,int v,int c){
19     E[o]=(Edge){v,hd[u],c,0};hd[u]=o++;
20     E[o]=(Edge){u,hd[v],0,0};hd[v]=o++;
21 }
22 queue<int>q;
23 bool bfs(){
24     for(int i=S;i<=T;i++)vis[i]=d[i]=0;
25     vis[S]=d[S]=1;q.push(S);
26     while(!q.empty()){
27         int u=q.front();q.pop();
28         for(int i=hd[u],v;~i;i=E[i].nt)if(E[i].c>E[i].f){
29             if(!vis[v=E[i].v])vis[v]=1,d[v]=d[u]+1,q.push(v);
30         }
31     }
32     return vis[T];
33 }
34 int dfs(int u,int F){
35     if(u==T||!F)return F;
36     int flow=0,f;
37     for(int i=cur[u];~i;i=E[i].nt){
38         int v=E[cur[u]=i].v;
39         if(d[v]==d[u]+1&&(f=dfs(v,min(E[i].c-E[i].f,F)))){
40             flow+=f,F-=f;
41             E[i].f+=f,E[i^1].f-=f;
42             if(!F)break;
43         }
44     }
45     return flow;
46 }
47 int dinic(){
48     int flow=0;
49     while(bfs()){for(int i=S;i<=T;i++)cur[i]=hd[i];flow+=dfs(S,inf);}
50     return flow;
51 }
52 int main(){
53     freopen("bzoj4177.in","r",stdin);
54     freopen("bzoj4177.out","w",stdout);
55     n=rd();m=rd();k=rd();
56     S=0,T=n+k+1;
57     for(int i=S;i<=T;i++)hd[i]=-1;
58     int ans=0;
59     for(int i=1,x;i<=n;i++){adde(S,i,x=rd());ans+=x;}
60     for(int i=1,x;i<=n;i++){adde(i,T,x=rd());ans+=x;}
61     for(int i=1,x,y,z;i<=m;i++){
62         x=rd();y=rd();z=rd();
63         adde(x,y,z);
64         adde(y,x,z);
65     }
66     for(int i=1,t,a,b;i<=k;i++){
67         t=rd();a=rd();b=rd();
68         ans+=b;
69         if(!a){
70             adde(S,i+n,b);
71             for(int j=1;j<=t;j++)adde(i+n,rd(),inf);
72         }else{
73             adde(i+n,T,b);
74             for(int j=1;j<=t;j++)adde(rd(),i+n,inf);
75         }
76     }
77     ans -= dinic();
78     printf("%d\n",ans);
79     return 0;
80 }
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 //一个很好的割;
91 //每个点(S,i,a[i])  (i,T,b[i]); 
92 //相同时代价 (x,y,b)
93 //集合的贡献:新建n+i号节点表示:a==0 , (S,n+i,b) (n+i,si,inf) ; a==1 (si,n+i,inf) (n+i,T,b);
94 //用总的正值减去最小割即可;
95 //注意第三步;
96 //20181210
97  
View Code

相关文章:

  • 2021-07-11
  • 2022-01-07
  • 2021-05-31
  • 2022-01-31
  • 2021-08-06
  • 2022-12-23
  • 2021-07-02
  • 2021-07-01
猜你喜欢
  • 2021-12-05
  • 2022-01-13
  • 2021-11-26
  • 2021-12-23
  • 2021-08-08
  • 2021-11-01
  • 2021-06-09
相关资源
相似解决方案