Poj 3469 Dual Core CPU(最小割)
Poj 3469 Dual Core CPU
题目描述
Dual Core CPU
Time Limit: 15000MS
Memory Limit: 131072K
Total Submissions: 28432
Description
As more and more computers are equipped with dual core CPU, SetagLilb, the Chief Technology Officer of TinySoft Corporation, decided to update their famous product - SWODNIW.
The routine consists of N modules, and each of them should run in a certain core. The costs for all the routines to execute on two cores has been estimated. Let’s define them as Ai and Bi. Meanwhile, M pairs of modules need to do some data-exchange. If they are running on the same core, then the cost of this action can be ignored. Otherwise, some extra cost are needed. You should arrange wisely to minimize the total cost.
Input
There are two integers in the first line of input data, N and M (1 ≤ N ≤ 20000, 1 ≤ M ≤ 200000) .
The next N lines, each contains two integer, Ai and Bi.
In the following M lines, each contains three integers: a, b, w. The meaning is that if module a and module b don’t execute on the same core, you should pay extra w dollars for the data-exchange between them.
Output
Output only one integer, the minimum total cost.
Sample Input
3 1
1 10
2 10
10 3
2 3 1000
Sample Output
13
题解
由《挑战程序设计》P236页。
思路:先转换为求最小割问题;再利用网络中最小割等于最大流求解。
一般将对象划分为两个集合的问题,可以使用最小割分隔。
设在核A上工作的模块集合为S,在核B上工作的集合为T;
所要求的花费为:
sum{A[i]|i属于S}+sum{B[i]|i属于T}+
sum{w[i]|(a[i]属于S,b[i]属于T)或(a[i]属于T,b[i]属于S)}
可以适当建边使得花费等价于割的容量。
- 对于sum{A[i]|i属于S},可以对每个模块向汇点t连边;切割时在S的模块到t的边都在割上。
- 对于sum{B[i]|i属于T},可以源点s向每个模块连边;
- 对于sum{w[i]|(a[i]属于S,b[i]属于T)或(a[i]属于T,b[i]属于S)},可以对每个w[i],在a[i]和b[i]间相互连边。
故只要求出网络的最小割即可。
由于最大流=最小割,所以跑最大流算法。
代码
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int maxn=2e5+5; const int INF=0x3f3f3f3f; const int inf=0x3f; class Edge{ public: int to,cap,nxt,rev; }; int head[maxn],cur[maxn]; Edge edge[maxn<<4]; int cnt=1; int N,M,S,T; int level[maxn]; void add(int u,int v, int cap){ edge[cnt].to=v;edge[cnt].cap=cap;edge[cnt].nxt=head[u];edge[cnt].rev=cnt+1; head[u]=cnt++; edge[cnt].to=u;edge[cnt].cap=0; edge[cnt].nxt=head[v];edge[cnt].rev=cnt-1; head[v]=cnt++; } void init(){ memset(head,0,sizeof(head)); memset(edge,0,sizeof(edge)); cnt=1; } void bfs(){ memset(level,-1,sizeof(level)); level[S]=0; queue<int> que; que.push(S); while(!que.empty()){ int now=que.front(); que.pop(); for(int i=head[now];i;i=edge[i].nxt){ Edge &e=edge[i]; if(level[e.to]<0&&e.cap>0){ level[e.to]=level[now]+1; que.push(e.to); } } } } int dfs(int now,int flow){ if(now==T) return flow; for(int i=cur[now];i;i=edge[i].nxt){ cur[now]=i; Edge &e=edge[i]; if(level[e.to]>level[now]&&e.cap>0){ int d=dfs(e.to, min(flow, e.cap)); if(d>0){ e.cap-=d; edge[e.rev].cap+=d; return d; } } } } void Dinic(){ int res=0; for(;;){ bfs(); if(level[T]<0) break; for(int i=1;i<=T;i++) cur[i]=head[i]; int d; while(d=dfs(S,INF)){ res+=d; } } printf("%d\n",res); } int main(){ int A,B,u,v,w; while(~scanf("%d%d",&N,&M)){ init(); S=N+1;T=N+2; for(int i=1;i<=N;i++){ scanf("%d%d",&A,&B); add(S,i,B);add(i,T,A); } for(int i=1;i<=M;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } Dinic(); } }
第一次理解最小割==最大流 这条性质的用处。对于分割两种集合最小耗费的问题有了新的思路~还要继续学习啊
- poj 3469 Dual Core CPU(最小割,好题)
- 【网络流#8】POJ 3469 Dual Core CPU 最小割【ISAP模板】 - 《挑战程序设计竞赛》例题
- POJ 3469 Dual Core CPU【最小割】
- poj 3469 Dual Core CPU 最小割
- POJ 3469 Dual Core CPU(最小割)
- POJ 3469 Dual Core CPU 最小割
- poj 3469 Dual Core CPU 最小割
- poj 3469 Dual Core CPU 最小割
- POJ 3469 Dual Core CPU (最小割建模)
- POJ 3469 Dual Core CPU(网络流之最小割)
- POJ3469_Dual Core CPU_最小割::分两部分
- POJ 3469 Dual Core CPU 最小割入门题
- POJ 3469 Dual Core CPU (最小割建模)
- 【poj 3469 】 Dual Core CPU 【最大流+最小割建图】
- Poj 3469 Dual Core CPU【最小割最大流-----Dinic】
- poj 3469 Dual Core CPU【求最小割容量】
- POJ 3469 Dual Core CPU 最小割问题
- 【POJ】3469 Dual Core CPU 最小割——项目分配问题
- POJ 3469 --Dual Core CPU【最小割】
- poj--3469--Dual Core CPU(最小割裸题)