HDU 3526 Computer Assembling(最小割)
http://acm.hdu.edu.cn/showproblem.php?pid=3526
题意:
有个屌丝要配置电脑,现在有n个配件需要购买,有两家公司出售这n个配件,还有m个条件是如果配件x和配件y在不同公司买的话,需要花费额外的w元。现在需要计算购买这n个配件的最小花费。
思路:
一开始想的费用流,但好像不太行??
其实一看到二选一的话就首先应该往最小割和二分图这个方向去想一想的。
这题用最小割来做,对于这m条件,在这两个顶点之间加两条有向边。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 const int INF = 0x3f3f3f3f; 9 const int maxn = 500+5; 10 11 int n,m; 12 13 struct Edge 14 { 15 int from,to,cap,flow; 16 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 17 }; 18 19 struct Dinic 20 { 21 int n,m,s,t; 22 vector<Edge> edges; 23 vector<int> G[maxn]; 24 bool vis[maxn]; 25 int cur[maxn]; 26 int d[maxn]; 27 28 void init(int n) 29 { 30 this->n=n; 31 for(int i=0;i<n;++i) G[i].clear(); 32 edges.clear(); 33 } 34 35 void AddEdge(int from,int to,int cap) 36 { 37 edges.push_back( Edge(from,to,cap,0) ); 38 edges.push_back( Edge(to,from,0,0) ); 39 m=edges.size(); 40 G[from].push_back(m-2); 41 G[to].push_back(m-1); 42 } 43 44 bool BFS() 45 { 46 queue<int> Q; 47 memset(vis,0,sizeof(vis)); 48 vis[s]=true; 49 d[s]=0; 50 Q.push(s); 51 while(!Q.empty()) 52 { 53 int x=Q.front(); Q.pop(); 54 for(int i=0;i<G[x].size();++i) 55 { 56 Edge& e=edges[G[x][i]]; 57 if(!vis[e.to] && e.cap>e.flow) 58 { 59 vis[e.to]=true; 60 d[e.to]=d[x]+1; 61 Q.push(e.to); 62 } 63 } 64 } 65 return vis[t]; 66 } 67 68 int DFS(int x,int a) 69 { 70 if(x==t || a==0) return a; 71 int flow=0, f; 72 for(int &i=cur[x];i<G[x].size();++i) 73 { 74 Edge &e=edges[G[x][i]]; 75 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 76 { 77 e.flow +=f; 78 edges[G[x][i]^1].flow -=f; 79 flow +=f; 80 a -=f; 81 if(a==0) break; 82 } 83 } 84 return flow; 85 } 86 87 int Maxflow(int s,int t) 88 { 89 this->s=s; this->t=t; 90 int flow=0; 91 while(BFS()) 92 { 93 memset(cur,0,sizeof(cur)); 94 flow +=DFS(s,INF); 95 } 96 return flow; 97 } 98 }DC; 99 100 int main() 101 { 102 //freopen("in.txt","r",stdin); 103 while(~scanf("%d%d",&n,&m)) 104 { 105 int src = 0, dst = n+1; 106 DC.init(dst+1); 107 for(int i=1;i<=n;i++) 108 { 109 int x;scanf("%d",&x); 110 DC.AddEdge(src,i,x); 111 } 112 for(int i=1;i<=n;i++) 113 { 114 int x;scanf("%d",&x); 115 DC.AddEdge(i,dst,x); 116 } 117 while(m--) 118 { 119 int u,v,w; 120 scanf("%d%d%d",&u,&v,&w); 121 DC.AddEdge(u,v,w); 122 DC.AddEdge(v,u,w); 123 } 124 printf("%d\n",DC.Maxflow(src,dst)); 125 } 126 return 0; 127 }