POJ 3469->Dual Core CPU(最大流最小割问题)
2016-09-06 21:00
357 查看
传送门:POJ 3469 Dual Core CPU
描述
题意:
双核CPU,n个模块,每个模块必须运行在某个CPU核心上,每个模块在cpu单核的消耗A和B,M对模块要共享数据,如果在同一个核心上不用消耗,否则需要耗费。安排N个模块,使得总耗费最小
思路:
用最小的费用将对象划分成两个集合的经典问题,课转换成最小割解决。
将两个cpu核心看成源点和汇点,其他模块分别与源点汇点连线(表示每个模块可以在任意cpu上运行),m对模块分别连双向边,要使得模块只能在一个cpu上运行,就是找到一个割,源点和汇点必不联通,耗费最少就是最小割,最小割最大流原理转换成求最大流。
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
/*ISAP+bfs初始化+栈优化
*/
const int maxn=200010;//点数的最大值
const int maxm=4400000;//边数的最大值
const int inf=0x3f3f3f3f;
struct Edge {
int to,next,cap,flow;
}edge[maxm];//注意是maxm
int tol;
int head[maxn];
int cur[maxn],d[maxn];// 当前弧下标 结点到汇点距离下界
int p[maxn],gap[maxn];//可增广路上的上一条弧 gap优化 //比dinic多的两个数组
void init(){
tol=0;
memset(head, -1, sizeof(head));
}
void addedge(int u,int v,int w,int rw = 0){
edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0;
edge[tol].next=head[u]; head[u]=tol++;
edge[tol].to=u; edge[tol].cap=rw; edge[tol].flow=0;
edge[tol].next=head[v]; head[v]=tol++;
}
int Q[maxn];
void bfs(int s,int t){//逆向进行bfs
memset(d, -1, sizeof(d));
memset(gap, 0, sizeof(gap));
gap[0]=1;
int front=0, rear=0;
d[t]=0;
Q[rear++]=t;
while(front!=rear){
int u=Q[front++];
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].to;
if(d[v]!=-1)continue;
Q[rear++]=v;
d[v]=d[u]+1;
gap[d[v]]++;
}
}
}
int S[maxn];
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int s,int t,int N){
bfs(s, t);
memcpy(cur, head, sizeof(head));
int top=0;
int u=s;
int ans=0;
while(d[s]<N){
if(u==t){
int Min=inf;
int inser;
for(int i=0; i<top; i++)//找最小残量值
if(Min>edge[S[i]].cap-edge[S[i]].flow){
Min=edge[S[i]].cap-edge[S[i]].flow;
inser=i;
}
for(int i=0; i<top; i++){//增广
edge[S[i]].flow+=Min;
edge[S[i]^1].flow-=Min;
}
ans+=Min;
top=inser;
u=edge[S[top]^1].to;
continue;
}
bool ok=false;
int v;
for(int i=cur[u]; i!=-1; i=edge[i].next){
v=edge[i].to;
if(edge[i].cap-edge[i].flow && d[v]+1==d[u]){////Advance前进
ok=true;
cur[u]=i;
break;
}
}
if(ok){
S[top++]=cur[u];
u=v;
continue;
}
//Retreat走不动了,撤退
int Min=N;
for(int i=head[u]; i!=-1; i=edge[i].next)
if(edge[i].cap-edge[i].flow && d[edge[i].to]<Min){
Min=d[edge[i].to];
cur[u]=i;
}
gap[d[u]]--;
if(!gap[d[u]])return ans;
d[u]=Min+1;
gap[d[u]]++;
if(u!=s)u=edge[S[--top]^1].to;//退一步,沿父边返回
}
return ans;
}
int n,m;
int main(){
while(~scanf("%d%d",&n,&m)){
init();
int u,v,w,s=0,t=n+1;
for(int i=1; i<=n; i++){
scanf("%d%d",&u,&v);
addedge(s, i, u);
addedge(i, t, v);
}
for(int i=1; i<=m; i++){
scanf("%d%d%d",&u,&v,&w);
addedge(u, v, w, w);
}
printf("%d\n",sap(s, t, n+2));
}
return 0;
}
描述
Dual Core CPU
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 Source POJ Monthly--2007.11.25, Zhou Dong |
双核CPU,n个模块,每个模块必须运行在某个CPU核心上,每个模块在cpu单核的消耗A和B,M对模块要共享数据,如果在同一个核心上不用消耗,否则需要耗费。安排N个模块,使得总耗费最小
思路:
用最小的费用将对象划分成两个集合的经典问题,课转换成最小割解决。
将两个cpu核心看成源点和汇点,其他模块分别与源点汇点连线(表示每个模块可以在任意cpu上运行),m对模块分别连双向边,要使得模块只能在一个cpu上运行,就是找到一个割,源点和汇点必不联通,耗费最少就是最小割,最小割最大流原理转换成求最大流。
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
/*ISAP+bfs初始化+栈优化
*/
const int maxn=200010;//点数的最大值
const int maxm=4400000;//边数的最大值
const int inf=0x3f3f3f3f;
struct Edge {
int to,next,cap,flow;
}edge[maxm];//注意是maxm
int tol;
int head[maxn];
int cur[maxn],d[maxn];// 当前弧下标 结点到汇点距离下界
int p[maxn],gap[maxn];//可增广路上的上一条弧 gap优化 //比dinic多的两个数组
void init(){
tol=0;
memset(head, -1, sizeof(head));
}
void addedge(int u,int v,int w,int rw = 0){
edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0;
edge[tol].next=head[u]; head[u]=tol++;
edge[tol].to=u; edge[tol].cap=rw; edge[tol].flow=0;
edge[tol].next=head[v]; head[v]=tol++;
}
int Q[maxn];
void bfs(int s,int t){//逆向进行bfs
memset(d, -1, sizeof(d));
memset(gap, 0, sizeof(gap));
gap[0]=1;
int front=0, rear=0;
d[t]=0;
Q[rear++]=t;
while(front!=rear){
int u=Q[front++];
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].to;
if(d[v]!=-1)continue;
Q[rear++]=v;
d[v]=d[u]+1;
gap[d[v]]++;
}
}
}
int S[maxn];
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int s,int t,int N){
bfs(s, t);
memcpy(cur, head, sizeof(head));
int top=0;
int u=s;
int ans=0;
while(d[s]<N){
if(u==t){
int Min=inf;
int inser;
for(int i=0; i<top; i++)//找最小残量值
if(Min>edge[S[i]].cap-edge[S[i]].flow){
Min=edge[S[i]].cap-edge[S[i]].flow;
inser=i;
}
for(int i=0; i<top; i++){//增广
edge[S[i]].flow+=Min;
edge[S[i]^1].flow-=Min;
}
ans+=Min;
top=inser;
u=edge[S[top]^1].to;
continue;
}
bool ok=false;
int v;
for(int i=cur[u]; i!=-1; i=edge[i].next){
v=edge[i].to;
if(edge[i].cap-edge[i].flow && d[v]+1==d[u]){////Advance前进
ok=true;
cur[u]=i;
break;
}
}
if(ok){
S[top++]=cur[u];
u=v;
continue;
}
//Retreat走不动了,撤退
int Min=N;
for(int i=head[u]; i!=-1; i=edge[i].next)
if(edge[i].cap-edge[i].flow && d[edge[i].to]<Min){
Min=d[edge[i].to];
cur[u]=i;
}
gap[d[u]]--;
if(!gap[d[u]])return ans;
d[u]=Min+1;
gap[d[u]]++;
if(u!=s)u=edge[S[--top]^1].to;//退一步,沿父边返回
}
return ans;
}
int n,m;
int main(){
while(~scanf("%d%d",&n,&m)){
init();
int u,v,w,s=0,t=n+1;
for(int i=1; i<=n; i++){
scanf("%d%d",&u,&v);
addedge(s, i, u);
addedge(i, t, v);
}
for(int i=1; i<=m; i++){
scanf("%d%d%d",&u,&v,&w);
addedge(u, v, w, w);
}
printf("%d\n",sap(s, t, n+2));
}
return 0;
}
相关文章推荐
- 随机收缩算法
- [BZOJ1266][AHOI2006][最短路][最小割]上学路线
- uva 11248
- poj 2914
- 【网络流之最小割模型】poj3469 BZOJ3144 UVA1212
- uva1660 最大流
- BZOJ 1001, 狼抓兔子
- hdu 3879 最小割模型
- bzoj1412[狼和羊的故事]最小割
- bzoj1001[狼爪兔子]最小割转最短路
- 浅谈最大流-最小割
- hihoCoder1252 2015北京区域赛 D.Kejin Game
- 网络流 最小割最大流定理
- 最小割算法
- BZOJ1497: [NOI2006]最大获利
- POJ 1815 Friendship
- bzoj-3144 切糕
- 【网络流】最大流:求最小割值、求(边)不交路径数量、求二分匹配最大匹配数
- POJ 3469 Dual Core CPU(最小割)
- HDU 5452 Minimum Cut (2015年沈阳赛区网络赛C题)