个人整理网络流

Posted 大米饼

tags:

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

说明: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

 

bzoj3504 [cqoi2014]危桥

题解:a1->a2 an次,b1->b2 bn次 , 边有通过次数的限制;直接跑最大流判断会有问题,因为可能会有a1->b2 , b1->a2的路径充当流量,交换a1,a2再反向跑一边即可;

 

 1 #include<bits/stdc++.h>
 2 #define inf 0x3f3f3f3f
 3 using namespace std;
 4 const int N=55,M=2510;
 5 int S,T,n,o,a1,a2,an,b1,b2,bn,hd[N],vis[N],cur[N],d[N],in[N],out[N],tot;
 6 struct Edge{int v,nt,c,f;}E[M<<1];
 7 void adde(int u,int v,int c){
 8     E[o]=(Edge){v,hd[u],c,0};hd[u]=o++;
 9     E[o]=(Edge){u,hd[v],0,0};hd[v]=o++;
10 }
11 queue<int>q;
12 bool bfs(){
13     for(int i=S;i<=T;i++)vis[i]=d[i]=0;
14     vis[S]=d[S]=1;q.push(S); 
15     while(!q.empty()){
16         int u=q.front();q.pop();
17         for(int i=hd[u],v;~i;i=E[i].nt)if(E[i].c>E[i].f){
18             if(!vis[v=E[i].v])vis[v]=1,d[v]=d[u]+1,q.push(v);
19         }
20     }
21     return vis[T];
22 }
23 int dfs(int u,int F){
24     if(!F||u==T)return F;
25     int flow=0,f;
26     for(int i=cur[u];~i;i=E[i].nt){
27         int v=E[cur[u]=i].v;
28         if(d[v]==d[u]+1&&(f=dfs(v,min(F,E[i].c-E[i].f)))){
29             flow+=f,F-=f;
30             E[i].f+=f,E[i^1].f-=f;
31             if(!F)break;
32         }
33     }
34     return flow;
35 }
36 int dinic(){
37     int flow=0;
38     while(bfs()){for(int i=S;i<=T;i++)cur[i]=hd[i];flow+=dfs(S,inf);}
39     return flow;
40 }
41 int main(){
42     freopen("bzoj3504.in","r",stdin);
43     freopen("bzoj3504.out","w",stdout);
44     while(~scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)){
45         a1++,a2++,b1++,b2++;
46         o=0;S=0;T=n+1;
47         for(int i=S;i<=T;i++)hd[i]=-1;
48         for(int i=1;i<=n;i++){
49             char ch[51];scanf("%s",ch+1);    
50             for(int j=1;j<=n;j++){
51                 if(ch[j]==\'O\')adde(i,j,1);
52                 else if(ch[j]==\'N\')adde(i,j,inf);
53             } 
54         }
55         adde(S,a1,an);adde(a2,T,an);
56         int pre1=hd[S],pre2=hd[T],pre3=hd[b1],pre4=hd[b2]; 
57         adde(S,b1,bn);adde(b2,T,bn);
58         if(dinic()!=an+bn){puts("No");continue;}
59         o-=4;for(int i=0;i<o;i++)E[i].f=0;
60         hd[S]=pre1,hd[T]=pre2,hd[b1]=pre3,hd[b2]=pre4;
61         adde(S,b2,bn);adde(b1,T,bn);
62         puts(dinic()==an+bn?"Yes":"No"); 
63     }
64     return 0; 
65 } 
66 
67 
68 
69 
70 
71 
72 
73 //一个比较巧妙的路径;
74 //通过yy可以发现,将第二条路径反向再做一遍就可以避免错误;
75 //20181210
76 
77 
78  
View Code

 

bzoj2039[2009国家集训队]employee

题解:首先<i,T,Ai>表示是否选择购买,考虑每对经理(i,j) , <S,i,Ei,j> <S,j,Ei,j> <i,j,2*Ei,j> , 这个网络可以化简:<S,i,$\\sum_{j}Ei,j$> <i,T,Ai> <i,j,2*Ei,j>,假设最小割为C,E的和为Sum,ans = 2*Sum – C;

 

 1 #include<bits/stdc++.h>
 2 #define ll long long 
 3 #define inf 1e18
 4 using namespace std;
 5 const int N=1010,M=2000010;
 6 int n,o,hd[N],vis[N],d[N],cur[N];
 7 struct Edge{int v,nt; ll c,f;}E[M<<1];
 8 char gc(){
 9     static char*p1,*p2,s[1000000];
10     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
11     return(p1==p2)?EOF:*p1++;
12 }
13 ll rd(){
14     ll x=0; char c=gc();
15     while(c<\'0\'||c>\'9\')c=gc();
16     while(c>=\'0\'&&c<=\'9\')x=(x<<1)+(x<<3)+c-\'0\',c=gc();
17     return x;
18 }
19 void adde(int u,int v,ll c){
20     E[o]=(Edge){v,hd[u],c,0};hd[u]=o++;
21     E[o]=(Edge){u,hd[v],0,0};hd[v]=o++;
22 }
23 queue<int>q;
24 bool bfs(){
25     for(int i=0;i<=n+1;i++)vis[i]=d[i]=0;
26     vis[0]=d[0]=1;q.push(0);
27     while(!q.empty()){
28         int u=q.front();q.pop();
29         for(int i=hd[u],v;~i;i=E[i].nt)if(E[i].c>E[i].f){
30             if(!vis[v=E[i].v])vis[v]=1,d[v]=d[u]+1,q.push(v);
31         }
32     }
33     return vis[n+1];
34 }
35 ll dfs(int u,ll F){
36     if(u==n+1||!F)return F;
37     int flow=0,f;
38     for(int i=cur[u];~i;i=E[i].nt){
39         int v=E[cur[u]=i].v;
40         if(d[v]==d[u]+1&&(f=dfs(v,min(E[i].c-E[i].f,F)))){
41             flow+=f,F-=f;
42             E[i].f+=f,E[i^1].f-=f;
43             if(!F)break;
44         }
45     }
46     return flow;
47 }
48 int dinic(){
49     int flow=0,f;
50     while(bfs()){
51         for(int i=0;i<=n+1;i++)cur[i]=hd[i];
52         while(f=dfs(0,inf))flow+=f;
53     }
54     return flow;
55 }
56 int main(){
57     freopen("bzoj2039.in","r",stdin);
58     freopen("bzoj2039.out","w",stdout);
59     n=rd();for(int i=0;i<=n+1;i++)hd[i]=-1;
60     for(int i=1;i<=n;i++)adde(i,n+1,rd());
61     ll ans=0;
62     for(int i=1;i<=n;i++){
63         ll sum=0,x;    
64         for(int j=1;j<=n;j++){
65             x=rd();sum+=x;
66             adde(i,j,x<<1);
67         }
68         adde(0,i,sum);
69         ans+=sum;
70     }
71     ans-=dinic(); 
72     printf("%lld\\n",ans);
73     return 0;
74 }
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 //这题卡常????
87 //luogu的我没过,开了O(2)好像也不行,bzoj勉强过了。。。。;
88 //(S,i,\\sum ei,j) (i,j,2*ei,j) (i,T,ai)
89 //20181210 
90 
91 
92 
93  
View Code

 

 

 

bzoj1797[AHOI2009]mincut

题解:

先做一遍最大流,考虑残量网络(要考虑反向边),

如果一条边有可能不满流那么它一定不可能为任何个割的一部分,一定满流那么它一定为某个割的一部分;

考虑一个最小割对应的划分集合S集合T集,跨越ST集合的边为割,那么残网中一定只存在T->S的边,假设存在S-T的边,要么为某个S->T的正向边要么为某个T->S反向边,前者不符合割后者不符合最小(感性理解吧。。。。);

所以在残网中做scc,设i所在scc为bl[i] , 首先bl[S]!=bl[T],对于残网中的边(u,v):

①如果bl[u]==bl[v],一定不可能为割边

②如果bl[u]!=bl[v]且bl[u]==bl[T]&&bl[v]==bl[S],则一定为割边,否则在缩点后的残网DAG上一定可以有一个另外的割;

 

  1 #include<bits/stdc++.h>
  2 #define inf 0x3f3f3f3f
  3 using namespace std;
  4 const int N=4010,M=60010;
  5 int S,T,n,m,o,hd[N],cur[N],vis[N],d[N],dfn[N],low[N],idx,bl[N],cnt;
  6 struct Edge{int u,v,nt,c,f;}E[M<<1];
  7 void adde(int u,int v,int c){
  8     E[o]=(Edge){u,v,hd[u],c,0};hd[u]=o++;
  9     E[o]=(Edge){v,u,hd[v],0,0};hd[v]=o++;
 10 }
 11 queue<int>q;
 12 bool bfs(){
 13     for(int i=1;i<=n;i++)vis[i]=d[i]=0;
 14     vis[S]=d[S]=1;q.push(S);
 15     while(!q.empty()){
 16         int u=q.front();q.pop();
 17         for(int i=hd[u],v;~i;i=E[i].nt)if(E[i].c>E[i].f){
 18             if(!vis[v=E[i].v])vis[v]=1,d[v]=d[u]+1,q.push(v);
 19         }
 20     }
 21     return vis[T];
 22 }
 23 int dfs(int u,int F){
 24     if(u==T||!F)return F;
 25     int flow=0,f;
 26     for(int i=cur[u];~i;i=E[i].nt){
 27         int v=E[cur[u]=i].v;
 28         if(d[v]==d[u]+1&&(f=dfs(v,min(F,E[i].c-E[i].f)))){
 29             flow+=f,F-=f;
 30             E[i].f+=f,E[i^1].f-=f;
 31             if(!F)break;
 32         }
 33     }
 34     return flow;
 35 }
 36 int dinic(){
 37     int flow=0;
 38     while(bfs()){
 39         for(int i=1;i<=n;i++)cur[i]=hd[i];
 40         flow+=dfs(S,inf);
 41     }
 42     return flow;
 43 }
 44 stack<int>s;
 45 void tarjan(int u){
 46     dfn[u]=low[u]=++idx;
 47     s.push(u);
 48     for(int i=hd[u];~i;i=E[i].nt)if(E[i].c>E[i].f){
 49         int v=E[i].v;
 50         if(dfn[v]){if(!d[v])low[u]=min(dfn[v],low[u]);}
 51         else {tarjan(v);low[u]=min(low[v],low[u]);}
 52     }
 53     if(dfn[u]==low[u]){
 54         int v;++cnt;
 55         do{
 56             v=s.top();s.pop();
 57             d[v]=1;bl[v]=cnt;
XMPP协议扩展:XEP-0198 流管理(Stream Management)中文翻译(个人整理,难免有翻译错的地方,请多多指正)

IOS开发-OC学习-常用功能代码片段整理

VS2015 代码片段整理

小程序各种功能代码片段整理---持续更新

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

json 个人的vscode的代码片段