题意:
有一些模块(modules)和一个双核处理器,一个模块可以在任意一个核上处理,每个核对应每个模块有个开销。现在有一些模块间需要数据交换,如果需要数据交换的模块在一个核上处理,则不需要额外开销,否则需要加上一个开销。现在需要完成所有模块,问最小需要多少开销。
如果没有这个额外的开销,那么每个模块只要选择开销小的那个核就行了。额外的开销给选择加上了限制。
题解:
最小割模型。
S和T分别表示两个核,每个模块和S,T连边求最小割就是了~
View Code
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 6 #define N 201000 7 #define M 2001000 8 #define INF 100000000 9 10 using namespace std; 11 12 int head[N],next[M],to[M],len[M],cnt,S,T,a[N],b[N],aa[M],bb[M],n,m,w[N],layer[N],q[M<<4]; 13 14 inline void add(int u,int v,int w) 15 { 16 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 17 to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++; 18 } 19 20 void read() 21 { 22 memset(head,-1,sizeof head); 23 for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); 24 for(int i=1;i<=m;i++) 25 { 26 scanf("%d%d%d",&aa[i],&bb[i],&w[i]); 27 add(aa[i],bb[i],w[i]); add(bb[i],aa[i],w[i]); 28 } 29 S=0; T=n+1; 30 for(int i=1;i<=n;i++) add(S,i,a[i]),add(i,T,b[i]); 31 } 32 33 bool bfs() 34 { 35 memset(layer,-1,sizeof layer); 36 int h=1,t=2,sta; 37 q[1]=S; layer[S]=0; 38 while(h<t) 39 { 40 sta=q[h++]; 41 for(int i=head[sta];~i;i=next[i]) 42 if(len[i]>0&&layer[to[i]]<0) 43 { 44 layer[to[i]]=layer[sta]+1; 45 q[t++]=to[i]; 46 } 47 } 48 return layer[T]!=-1; 49 } 50 51 int find(int u,int cur_flow) 52 { 53 if(u==T) return cur_flow; 54 int result=0,tmp=0; 55 for(int i=head[u];~i&&result<cur_flow;i=next[i]) 56 if(len[i]>0&&layer[to[i]]==layer[u]+1) 57 { 58 tmp=find(to[i],min(len[i],cur_flow-result)); 59 len[i]-=tmp; len[i^1]+=tmp; result+=tmp; 60 } 61 if(!result) layer[u]=-1; 62 return result; 63 } 64 65 int dinic() 66 { 67 int ans=0; 68 while(bfs()) ans+=find(S,INF); 69 return ans; 70 } 71 72 int main() 73 { 74 while(scanf("%d%d",&n,&m)!=EOF) 75 { 76 read(); 77 printf("%d",dinic()); 78 } 79 return 0; 80 }