题目: http://poj.org/problem?id=3469
题目大意:有两个cpu, 给定n个任务要在某个cpu上运行,给出n个任务分别在两个cpu上运行的消耗a[i],b[i]; 并且给定m个关系。
关系p,q, c是指如果任务p和q不在同一个cpu上运行,则需要额外的消耗c。如果有两个任务同时在听一个cpu运行,则额外消耗不计。
考查点:最小割
思路:读完题以后,就感觉像是网络流的题,感觉两个cpu正好像天然的源点和汇点,用第一个cpu向每个任务连一条流量为a[i]的边,表示第i个任务在cpu-1上运行的消耗。从每个任务向第二个cpu连一条流量为b[i]的边,表示任务i在cpu-2上运行消耗的时间,那么一个割的含义就是把任务i分配到某个cpu上运行。但是,第二个条件控制?如何增加两个关联的任务不在同一个cpu上运行的额外消耗?经过漫长的思考,最后发现只要在p,q之间加一条流量为c双向边,这样单纯的割cpu与任务之间的流就不能把任务割掉了。这样就实现了第二个条件。因此,见图的思路就清晰了,算法方面,由于此图可能层次明显,故用dinic算法。
此外此题是测速度的题
提交情况 Accepted 1 次
收获 :对建图有了更深的认识,对dinic的当前狐优化有了更好的
认识
经验:要把每条流的含义搞清楚
AC code:
#include <stdio.h>
#include <string.h>
#define MAXN 21000
#define MAXM 10000000
#define INF 2100000000
int to[MAXM], flux[MAXM], next[MAXM], point[MAXN];
int vis[MAXN], d[MAXN], cur[MAXN];
int ad, n;
int bfs(int s, int t){
int queue[MAXN], b[MAXN];
int head = 0, tail = 1;
int u, v, p;
memset(d, -1, sizeof(d));
queue[head] = s;
d[s] = 0;
while(head < tail){
u = queue[head ++];
for(p = point[u]; ~p; p = next[p]){
v = to[p];
if(flux[p] && d[v] == -1){
d[v] = d[u] + 1;
queue[tail ++] = v;
if(d[t] > 0) return 1;
}
}
}
return (d[t] > 0);
}
int dfs(int x, int low){
if(x == n + 1) return low;
vis[x] = 1;
for(int p = cur[x], temp, v; ~ p; p = next[p], cur[x] = p){
v = to[p];
if(!vis[v] && flux[p] && d[x] == d[v] - 1)
if(temp = dfs(v, low < flux[p] ? low : flux[p])){
flux[p] -= temp;
flux[p ^ 1] += temp;
return temp;
}
}
return 0;
}
int main(){
int m, i;
int x, y , z;
int ans, flow;
while(~scanf("%d %d", &n, &m)){
ans = 0;
memset(point , -1, sizeof(point));
ad = 0;
for(i = 1; i <= n; i ++){
scanf("%d %d", &x, &y);
to[ad] = i; flux[ad] = x; next[ad] = point[0]; point[0] = ad ++;
to[ad] = 0; flux[ad] = 0; next[ad] = point[i]; point[i] = ad ++;
to[ad] = n + 1; flux[ad] = y; next[ad] = point[i]; point[i] =ad ++;
to[ad] = i; flux[ad] = 0; next[ad] = point[n + 1]; point[n + 1] = ad ++;
}
while(m --){
scanf("%d %d %d", &x, &y, &z);
to[ad] = y; flux[ad] = z; next[ad] = point[x]; point[x] = ad ++;
to[ad] = x; flux[ad] = z; next[ad] = point[y]; point[y] = ad ++;
}
while(bfs(0, n + 1)){
for(i = 0; i <= n + 1; i ++) cur[i] = point[i];
while(1){
memset(vis, 0, sizeof(vis));
if((flow = dfs(0, INF)) == 0) break;
ans += flow;
}
}
printf("%d\n", ans);
}
return 0;
}