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
*/
相關文章
- 最大流最小割
- 最大流 dinic演算法演算法
- 網路流(最大流,最小割)
- 網路最大流 Dinic演算法演算法
- 偷寶石(最大流轉化最小割)
- Dinic/ISAP求最大流
- 網路流最大流、最小割學習筆記筆記
- 網路流-最小割
- bzoj4808: 馬(最小割)
- bzoj3275: Number(最小割)
- POJ1273 Drainage Ditches【網路流 最大流】AI
- 網路中最小費用最大流
- bzoj1391: [Ceoi2008]order(最小割)
- Networking POJ - 1287(kuangbin最小生成樹)
- 1.1.3.3 最小割之最小權覆蓋集、最大權獨立集
- poj--3264Balanced Lineup+ST演算法求區間最大最小值演算法
- SPOJ - OPTM Optimal Marks(進位制拆分+最小割)
- 最大流 EdmondsKarp演算法演算法
- bzoj3175: [Tjoi2013]攻擊裝置(最小割)
- POJ 1734 Sightseeing trip Floyd求無向圖最小環
- 【BZOJ-1565】植物大戰殭屍 拓撲排序 + 最小割排序
- 論文導讀 | 最小屬性割RDF資料劃分
- POJ--2406Power Strings+KMP求字串最小週期KMP字串
- BZOJ1927: [Sdoi2010]星際競速(最小費用最大流 最小路徑覆蓋)
- Intel core 2 QX6600 CPUIntel
- 演算法 最小高度樹演算法
- P2057 [SHOI2007]善意的投票 / [JLOI2010]冠軍調查( 最小割 )
- P3388 【模板】割點(割頂)
- 最小生成樹的演算法演算法
- 最小生成樹__Kurskal演算法演算法
- 最小生成樹__Prim演算法演算法
- 無向圖最小割問題取得新突破,谷歌研究獲SODA 2024最佳論文獎谷歌
- cpu的排程演算法演算法
- POJ3268 Silver Cow Party【Dijkstra演算法+思維】演算法
- POJ 1330 LCA最近公共祖先 離線tarjan演算法演算法
- 最小生成樹——Prim演算法和Kruscal演算法演算法
- 最小生成樹-Prim演算法和Kruskal演算法演算法
- 最小生成樹:Kruskal演算法和Prim演算法演算法
- 洛谷 P3388 【模板】割點(割頂)