Time Limit: 15000MS | Memory Limit: 131072K | |
Total Submissions: 22966 | Accepted: 9993 | |
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
一个模块可以在任意一个核上处理,
模块i在核A的花费为Ai 在核B上的花费为Bi
现在有M组模块组合(ai,bi),模块间需要数据交换,
如果这两个模块在一个核上处理,没有额外花费, 否则会额外花费wi
现在需要完成所有模块,问最小花费。
源点s和n个点连接,容量是Ai, n个点和t连接,容量是Bi。
对于每个模块组合,ai连接bi,容量wi,bi连接ai,容量wi。
这样的话,按照最小割的定义,n个任务一些要被分到S,另一些要被分到T,这两部分之间没有边的连接。正好是题目的要求。
用了Dinic邻接表的模板
求最小割 = 求最大流
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#define pi acos(-1)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef pair<int, int> P;
const int maxn = 1e5 + 5;
const int mod = 1e8;
struct edge{
int to, cap, rev;
};
vector<edge>G[maxn];
int level[maxn]; // 顶点到源点的距离标号
int iter[maxn]; // 当前弧,在其之前的边已经没有用了
int n, m;
//向图中增加一条从from到to的容量为cap的边
void add_edge(int from, int to, int cap){
G[from].push_back((edge){to, cap, G[to].size()});
G[to].push_back((edge){from, 0, G[from].size()-1});
}
//通过BFS计算从源点出发的距离标号
void BFS(int s)
{
memset(level, -1, sizeof(level));
queue<int> q;
level[s] = 0;
q.push(s);
while (!q.empty()){
int u = q.front(); q.pop();
for (int i = 0; i < G[u].size(); i++){
edge &e = G[u][i];
if (e.cap>0 && level[e.to]<0){
level[e.to] = level[u] + 1;
q.push(e.to);
}
}
}
}
// 通过DFS寻找增广路径
int DFS(int u, int t, int f)
{
if (u == t) return f;
for (int &i = iter[u]; i < G[u].size(); i++){
edge &e = G[u][i];
if (e.cap > 0 && level[u] < 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;
}
// 求解从s到t的最大流
int Max_Flow(int s, int t)
{
int flow = 0;
while (1){
BFS(s);
if (level[t] < 0) return flow;
memset(iter, 0, sizeof(iter));
int f;
while ((f = DFS(s, t, inf)) > 0)
flow += f;
}
}
int main(void)
{
// freopen("C:\\Users\\wave\\Desktop\\NULL.exe\\NULL\\in.txt","r", stdin);
int i, j, a, b, w;
while (cin >> n >> m){
memset(G, 0, sizeof(G));
for (i = 1; i <= n; i++){
scanf("%d %d", &a, &b);
add_edge(n+1, i, a); // 我设定的s为n+1, t为n+2
add_edge(i, n+2, b);
}
for (i = 1; i <= m; i++){
scanf("%d %d %d", &a, &b, &w);
add_edge(a, b, w);
add_edge(b, a, w);
}
printf("%d\n", Max_Flow(n+1, n+2));
}
return 0;
}