POJ 3469 Dual Core CPU (最大流最小割經典題)
Time Limit: 15000MS | Memory Limit: 131072K | |
Total Submissions: 24781 | Accepted: 10732 | |
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
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
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
題意:給你n個CPU,每個CPU都有兩種mode,而且每個CPU只能選擇一種mode執行,然後給你m個限制條件,a,b,c,如果a和b兩個cpu用的不是一種mode,就需要c個花費來彌補這個問題,問每個CPU都執行的最小花費。
思路:大家都說看到兩個集合一般就是最小割,記筆記記筆記(網路流還是要多刷題啊
1、經典的最小割模型。建圖如下:
①建立源點S,將其連入各個CPU,權值設定為Ai。
②建立匯點T,將各個CPU連入匯點,權值設定為Bi。
③對於m個限制,(a,b,c),將a連入b,權值設定為c,將b連入a,權值設定也是c。
2、那麼為什麼對於m個限制這樣建圖就能夠達到目的選取最小割呢?
我們來看幾個圖:
①假設我們現在m==0
那麼很明顯,我們的最大流==最小割==2+3=5,同時也就是最小花費。跑得的殘餘網路:
1、經典的最小割模型。建圖如下:
①建立源點S,將其連入各個CPU,權值設定為Ai。
②建立匯點T,將各個CPU連入匯點,權值設定為Bi。
③對於m個限制,(a,b,c),將a連入b,權值設定為c,將b連入a,權值設定也是c。
2、那麼為什麼對於m個限制這樣建圖就能夠達到目的選取最小割呢?
我們來看幾個圖:
①假設我們現在m==0
那麼很明顯,我們的最大流==最小割==2+3=5,同時也就是最小花費。跑得的殘餘網路:
通過上面兩個圖(轉自:mengxiang000), 我們會發現, 如果沒有限制條件, 那肯定就是最小割,每個點只能屬於一個集合, 最小割就是最優值, 它要求不在同一個陣營選會有額外話費, 那就在這兩個點連一個無向邊,你會發現要斷開這兩個集合,如果斷開不是一個集合的邊的話,必須要斷開中間的某條線跟左右集合裡的一條邊~
程式碼:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 120050;
const int maxv = 200005;
const int INF = 0x3f3f3f3f;
int head[maxn], cur[maxn], d[maxn], n, m, s, t, k, sum;
struct node
{
int v, w, next;
}edge[3000005];
void addEdge(int u, int v, int w)
{
edge[k].v = v;
edge[k].w = w;
edge[k].next = head[u];
head[u] = k++;
edge[k].v = u;
edge[k].w = 0;
edge[k].next = head[v];
head[v] = k++;
}
int bfs()
{
memset(d, 0, sizeof(d));
d[s] = 1;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u = q.front();
if(u == t) return 1;
q.pop();
for(int i = head[u]; i != -1; i = edge[i].next)
{
int to = edge[i].v, w = edge[i].w;
if(w && d[to] == 0)
{
d[to] = d[u] + 1;
if(to == t) return 1;
q.push(to);
}
}
}
return 0;
}
int dfs(int u, int maxflow)
{
if(u == t) return maxflow;
int ret = 0;
for(int i = cur[u]; i != -1; i = edge[i].next)
{
int to = edge[i].v, w = edge[i].w;
if(w && d[to] == d[u]+1)
{
int f = dfs(to, min(maxflow-ret, w));
edge[i].w -= f;
edge[i^1].w += f;
ret += f;
if(ret == maxflow) return ret;
}
}
return ret;
}
int Dinic()
{
int ans = 0;
while(bfs())
{
memcpy(cur, head, sizeof(head));
ans += dfs(s, INF);
}
return ans;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
s = 0, t = n+1, k = 0;
memset(head, -1, sizeof(head));
int x, y, z;
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &x, &y);
addEdge(s, i, x);
addEdge(i, t, y);
}
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &x, &y, &z);
addEdge(x, y, z);
addEdge(y, x, z);
}
printf("%d\n", Dinic());
}
return 0;
}
1、經典的最小割模型。建圖如下:
①建立源點S,將其連入各個CPU,權值設定為Ai。
②建立匯點T,將各個CPU連入匯點,權值設定為Bi。
③對於m個限制,(a,b,c),將a連入b,權值設定為c,將b連入a,權值設定也是c。
2、那麼為什麼對於m個限制這樣建圖就能夠達到目的選取最小割呢?
我們來看幾個圖:
①假設我們現在m==0
那麼很明顯,我們的最大流==最小割==2+3=5,同時也就是最小花費。跑得的殘餘網路: