POJ 3469-Dual Core CPU(Dinic 最大流/最小割演算法)
Time Limit: 15000MS | Memory Limit: 131072K | |
Total Submissions: 22932 | Accepted: 9983 | |
Case Time Limit: 5000MS |
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
Source
POJ Monthly--2007.11.25, Zhou Dong
題目意思:
有兩個CPU,它們之間有N個模組,每個模組必須執行在某個CPU中。
每個模組在每個CPU中執行的耗費分別是Ai和Bi。
有M對模組之間需要共享資料,如果它們不是在同一個CPU中執行,需要W的耗費,反之不需要。
如何安排這N個模組能夠使得耗費最小?
解題思路:
因為每個模組必須執行在某個CPU中,所以想到要建圖求最小割,又由最大流最小割定理可知,直接求出最大流即可。
注意要雙邊建圖。
兩塊CPU分別作為源點和匯點,Ai是連線源點的容量,Bi是連線匯點的容量。
W連線兩塊需要共享資料的模組,建圖如上,求解S到T的最大流即為最小割。
試了一下Ford-Fulkerson 標號法求網路最大流……Orz可惜鄰接矩陣不能開得太大,一直MLE…果斷改Dinic!!
①
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iomanip>
#include <algorithm>
#define max 21000
#define maxn 1000000
#define INF 0xfffffff
using namespace std;
struct edge
{
int to,cap,rev;//終點、容量、反向邊
};
vector<edge>G[maxn];//圖的鄰接表表示
int level[maxn];//頂點到源點的距離標號
int iter[maxn];//當前弧,在其之前的邊都已經沒有用了
void add_edge(int from,int to,int cap)//向圖中增加一條從from到to的容量為cap的邊
{
G[from].push_back((edge)
{
to,cap,G[to].size()
});
G[to].push_back((edge)
{
from,0,G[from].size()-1
});
}
void bfs(int s)//通過BFS計算從源點出發的距離標號
{
memset(level,-1,sizeof(level));
queue<int>que;
level[s]=0;
que.push(s);
while(!que.empty())
{
int v=que.front();
que.pop();
for(int i=0; i<G[v].size(); ++i)
{
edge &e=G[v][i];
if(e.cap>0&&level[e.to]<0)
{
level[e.to]=level[v]+1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f)//DFS尋找增廣路
{
if(v==t) return f;
for(int &i=iter[v]; i<G[v].size(); ++i)
{
edge &e=G[v][i];
if(e.cap>0&&level[v]<level[e.to])
{
int d=dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int Dinic(int s,int t)//求解s到t的最大流
{
int maxflow=0;
while(1)
{
bfs(s);
if(level[t]<0) return maxflow;
memset(iter,0,sizeof(iter));
int f;
while((f=dfs(s,t,INF))>0)
maxflow+=f;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i,a,b,w;
int n,m;
cin>>n>>m;
for(i=1; i<=n; ++i)
{
cin>>a>>b;
add_edge(0,i,a);
add_edge(i,n+1,b);
add_edge(i,0,a);//雙向邊
add_edge(n+1,i,b);
}
while(m--)
{
cin>>a>>b>>w;
add_edge(a,b,w);
add_edge(b,a,w);//雙向邊
}
cout<<Dinic(0,n+1)<<endl;
return 0;
}
/*
3 1
1 10
2 10
10 3
2 3 1000
*/
②
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iomanip>
#include <algorithm>
#define nmax 21000
#define mmax 1000000
#define INF 0xfffffff
using namespace std;
struct Edge
{
int u,v,cap,flow;
int next;
Edge(int a=0,int b=0,int c=0,int d=0):u(a),v(b),cap(c),flow(d) {}
};
struct Edgelist
{
int start[nmax];
int last[nmax];
int t,i;
Edge arc[mmax];
void Clear()//清除
{
t=0;
memset(last,-1,sizeof(last));
}
void Push_back(Edge edge)//追加
{
edge.next=-1;
arc[t]=edge;
if(last[edge.u]!=-1) arc[last[edge.u]].next=t;
else start[edge.u]=t;
last[edge.u]=t;
++t;
}
void add_arc(Edge edge//建立雙向弧
{
Push_back(edge);
Push_back(Edge(edge.v,edge.u,edge.cap));
}
} net;
int q[2][nmax];//陣列模擬滾動數列
int q1[2],q2[2],qnow;
void Push_queue(int a)//入佇列
{
q[qnow][q2[qnow]++]=a;
}
int Pop_queue()//出佇列
{
return q[qnow^1][q1[qnow^1]++];
}
void Switch_queue()//滾動佇列
{
qnow^=1;
q1[qnow]=0,q2[qnow]=0;
}
bool Empty_queue()//判空
{
return q1[qnow^1]>=q2[qnow^1];
}
int Size_queue()//大小
{
return q2[qnow^1]-q1[qnow^1];
}
int n,m;
int dis[nmax];//層次網路(距離標號)
int path[nmax],deep;//路徑
int cur[nmax];
bool BFS()//構建層次網路
{
int i,l,u,v;
memset(dis,-1,sizeof(dis));
dis[0]=0;
qnow=0;
Switch_queue();
Push_queue(0);
Switch_queue();
while(!Empty_queue())
{
l=Size_queue();
while(l--)
{
u=Pop_queue();
for(i=net.start[u]; i!=-1; i=net.arc[i].next)
{
v=net.arc[i].v;
if(dis[v]==-1&&net.arc[i].cap>net.arc[i].flow)
{
Push_queue(v);
dis[v]=dis[u]+1;
if(v==n) return true;
}
}
}
Switch_queue();
}
return false;
}
int Dinic()//求最大流
{
int i,u,neck,pos,res;
int maxflow=0;
while(BFS())
{
memcpy(cur,net.start,sizeof(cur));
deep=u=0;
while(1)//最短路增廣
{
if(u==n)//存在增廣路則修改殘餘網路
{
neck=INF;
for(i=0; i<deep; ++i)
{
res=net.arc[path[i]].cap-net.arc[path[i]].flow;
if(res<neck)
{
neck=res;
pos=i;
}
}
maxflow+=neck;
for(i=0; i<deep; ++i)
{
net.arc[path[i]].flow+=neck;
net.arc[path[i]^1].flow-=neck;
}
deep=pos;
u=net.arc[path[deep]].u;
}
for(i=cur[u]; i!=-1; i=net.arc[i].next)//在層次網路中進行增廣
{
if(net.arc[i].cap>net.arc[i].flow&&dis[u]+1==dis[net.arc[i].v])
break;
}
cur[u]=i;
if(i!=-1)
{
path[deep++]=i;
u=net.arc[i].v;
}
else
{
if(deep==0) break;
dis[u]=-1;
u=net.arc[path[--deep]].u;
}
}
}
return maxflow;//最大流
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i,a,b,w;
cin>>n>>m;
net.Clear();
for(i=1; i<=n; ++i)//插入弧
{
cin>>a>>b;
net.add_arc(Edge(0,i,a));
net.add_arc(Edge(i,n+1,b));
}
while(m--)
{
cin>>a>>b>>w;
net.add_arc(Edge(a,b,w));
}
++n;
cout<<Dinic()<<endl;
return 0;
}
/*
3 1
1 10
2 10
10 3
2 3 1000
*/
相關文章
- POJ 3308 Paratroopers 最小割、最大流OOP
- 最大流 dinic演算法演算法
- 網路流(最大流,最小割)
- 網路最大流 Dinic演算法演算法
- matlab練習程式(最大流/最小割)Matlab
- 偷寶石(最大流轉化最小割)
- Dinic/ISAP求最大流
- 網路流最大流、最小割學習筆記筆記
- POJ 2914-Minimum Cut(Stoer_Wagner最小割演算法)演算法
- POJ 2195-Going Home(KM演算法/最小費用最大流演算法)Go演算法
- POJ 2195 Going Home 最小費用最大流Go
- POJ 2195 Going Home (最小費用最大流)Go
- poj 3436 最大流的增廣路演算法演算法
- 網路流-最小割
- spoj 839 最小割應用
- POJ 1523 SPF (無向圖求割點 tarjan演算法)演算法
- POJ 3565 Ants (最小權完美匹配 KM演算法)演算法
- bzoj2127: happiness(最小割)APP
- POJ 1459-Power Network(最大流-Edmond-Karp演算法)演算法
- poj1087 網路最大流
- 網路中最小費用最大流
- 1.1.3.3 最小割之最小權覆蓋集、最大權獨立集
- POJ 1273-Drainage Ditches(最大流-Edmond-Karp演算法/模板)AI演算法
- SPOJ - OPTM Optimal Marks(進位制拆分+最小割)
- POJ 3436-ACM Computer Factory(最大流輸出路徑-Edmond-Karp演算法)ACM演算法
- POJ 2051(最小堆/優先佇列)佇列
- POJ1273 Drainage Ditches【網路流 最大流】AI
- 最大流 EdmondsKarp演算法演算法
- 網路最大流演算法演算法
- 論文導讀 | 最小屬性割RDF資料劃分
- poj 3164 Command Network(最小樹形圖模板題)朱_ 劉演算法演算法
- POJ 基本演算法演算法
- 【BZOJ-1565】植物大戰殭屍 拓撲排序 + 最小割排序
- poj--3264Balanced Lineup+ST演算法求區間最大最小值演算法
- POJ 1465-Multiple(BFS-最小整倍數)
- 經典演算法-最大流問題演算法
- Intel core 2 QX6600 CPUIntel
- linux 下檢視物理CPU,邏輯CPU,CPU core,超執行緒Linux執行緒