【最小割】BZOJ3438-小M的作物(Rank 2???!!!)(含新款Dinic模板)

一开始被T掉了之后,才害怕地发现之前写的Dinic基本上都是错的??!!!正确的写在注释里了,注意一下(;3<)馬鹿やろ

一个丧心病狂的优化前后效率对比:🐕

【题目大意】

有A、B两块地和n个农作物,每个农作物种在A可产生ai价值,种在B可产生bi价值。又存在m种组合,若组合里所有农作物均种在A可产生c1i价值,均种在B可产生c2i价值。问如何种价值最大?

【思路】

建立源点S和汇点T,代表A、B两块地。

对于某个农作物xi,由S向xi连容量为ai的边,由xi向T连容量为bi的边。

对于组合m,我们建立两个点y1i,y2i,由S向y1i连容量为c1i的边,由y2i向T连容量为c2i的边。由y1i向组合里的每个x连容量为INF的边,由组合里的每个x向y2i容量为INF的边。

(关于有人问会不会某个组合里的点有的种在了A,有的种在了B,不会呀,否则S到T就有一条通路了)

要求的就是最小割=最大流。答案=总价值-最小割。

Rank2了,天真地想一想如果加个读入优化,再加个当前弧优化,再不用STL,能不能Rank1呢

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #define S 0
  8 #define T (m*2+n)+1
  9 using namespace std;
 10 const int MAXN=1000+50;
 11 const int INF=0x7fffffff;
 12 struct node
 13 {
 14     int to,pos,cap;
 15 };
 16 int m,n; 
 17 vector<node> E[MAXN*3];
 18 int dis[MAXN*3],ans,a[MAXN],b[MAXN];
 19  
 20 void addedge(int u,int v,int w)
 21 {
 22     E[u].push_back((node){v,E[v].size(),w});
 23     E[v].push_back((node){u,E[u].size()-1,0});
 24 }
 25  
 26 void init()
 27 {
 28     ans=0;
 29     scanf("%d",&n);
 30     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
 31     for (int i=1;i<=n;i++) scanf("%d",&b[i]);
 32     scanf("%d",&m);
 33     for (int i=1;i<=n;i++)
 34     {
 35         ans+=a[i]+b[i];
 36         addedge(S,i,a[i]);
 37         addedge(i,T,b[i]);
 38     }
 39     int cnt=n;
 40     for (int i=1;i<=m;i++)
 41     {
 42         int k,c1,c2,x;
 43         scanf("%d%d%d",&k,&c1,&c2);
 44         ++cnt,addedge(S,cnt,c1);
 45         ++cnt,addedge(cnt,T,c2);
 46         ans+=c1+c2;
 47         for (int j=0;j<k;j++)
 48         {
 49             scanf("%d",&x);
 50             addedge(cnt-1,x,INF);
 51             addedge(x,cnt,INF);
 52         }
 53     }
 54 } 
 55  
 56 bool bfs()
 57 {
 58     memset(dis,-1,sizeof(dis));
 59     queue<int> que;
 60     while (!que.empty()) que.pop(); 
 61     que.push(S);
 62     dis[S]=0;
 63     while (!que.empty())
 64     {
 65         int head=que.front();que.pop();
 66         if (head==T) return true;    //首次抵达T即可返回,不需要整张图全部分层 
 67         for (int i=0;i<E[head].size();i++)
 68         {
 69             node tmp=E[head][i];
 70             if (dis[tmp.to]==-1 && tmp.cap)
 71             {
 72                 dis[tmp.to]=dis[head]+1;
 73                 que.push(tmp.to);
 74             }
 75         }
 76     }
 77     return false;
 78 }
 79  
 80 int dfs(int s,int e,int f)
 81 {
 82     if (s==e) return f;
 83     int ret=0;
 84     for (int i=0;i<E[s].size();i++)
 85     {
 86         node &tmp=E[s][i];
 87         if (dis[tmp.to]==dis[s]+1 && tmp.cap)
 88         {
 89             int delta=dfs(tmp.to,e,min(f,tmp.cap));
 90             if (delta>0)
 91             {
 92                 tmp.cap-=delta;
 93                 E[tmp.to][tmp.pos].cap+=delta;
 94                 f-=delta;
 95                 ret+=delta;
 96                 if (f==0) return ret;
 97             }
 98             else dis[tmp.to]=-1;//注意一下这里要清为-1,很重要★★★★★ 
 99         }
100     } 
101     return ret;
102 }
103  
104 void dinic()
105 {
106     while (bfs())
107     {
108         int f=dfs(S,T,INF);
109         if (f) ans-=f;else break;
110     }
111     printf("%d\n",ans);
112 }
113  
114 int main()
115 {
116     init();
117     dinic();
118     return 0;
119 }

 ---提炼一个Dinic模板出来--

 1 bool bfs()
 2 {
 3     memset(dis,-1,sizeof(dis));
 4     queue<int> que;
 5     while (!que.empty()) que.pop(); 
 6     que.push(S);
 7     dis[S]=0;
 8     while (!que.empty())
 9     {
10         int head=que.front();que.pop();
11         if (head==T) return true;    //首次抵达T即可返回,不需要整张图全部分层 
12         for (int i=0;i<E[head].size();i++)
13         {
14             node tmp=E[head][i];
15             if (dis[tmp.to]==-1 && tmp.cap)16             {
17                 dis[tmp.to]=dis[head]+1;
18                 que.push(tmp.to);
19             }
20         }
21     }
22     return false;
23 }
24  
25 int dfs(int s,int e,int f)
26 {
27     if (s==e) return f;
28     int ret=0;
29     for (int i=0;i<E[s].size();i++)
30     {
31         node &tmp=E[s][i];
32         if (dis[tmp.to]==dis[s]+1 && tmp.cap)
33         {
34             int delta=dfs(tmp.to,e,min(f,tmp.cap));
35             if (delta>0)
36             {
37                 tmp.cap-=delta;
38                 E[tmp.to][tmp.pos].cap+=delta;
39                 f-=delta;
40                 ret+=delta;
41                 if (f==0) return ret;
42             }
43             else dis[tmp.to]=-1;//注意一下这里要清为-1,很重要★★★★★ 
44         }
45     } 
46     return ret;
47 }
48  
49 void dinic()
50 {
51     int flow=0;
52     while (bfs())
53     {
54         int f=dfs(S,T,INF);
55         if (f) flow+=f;else break;
56     }
57     printf("%d\n",flow);
58 }

 

posted @ 2016-07-29 13:28  iiyiyi  阅读(368)  评论(0编辑  收藏  举报