Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

谈一谈这道题用最小割的原因

Posted by ZHXS at 2021-08-07 22:24:29 on Problem 3469
感觉网上许多题解都没有说清楚为什么这道题需要用最小割来解决。。我来谈谈我的想法
首先考虑一下M == 0也就是模块之间没有边的情形,我们创建一个图,其中可以把s看作是第一个核,t看作是第二个核,对于模块i,我们都连一条(s, i)和(i, t)的边。当M == 0的时候,对与模块i而言,由于模块只能工作在一个CPU上,要么割掉(s, i),要么割掉(i, t), 不妨这样考虑:割掉(s, i)表明模块i在s上运行,割掉(i, t)表明模块i在t上运行。那么当M == 0时,被割掉的边,就是我们要选择的分配方案,也就是最小开销。
再次强调一遍,此处被割掉的边才是我们选择的方案,换言之,如果s点对应核A,t点对应核B,即T集合中除去汇点t之外的模块都是交给核B处理的(因为所有从S到T的边都被割去了,被割掉的才是核A选择的)
当M != 0时,对于模块u和模块v而言,存在权值为w的一条边,有两种情形:
1.u和v在同一个核运行
2.u和v在不同的核运行
首先考虑情形1,那就是说要么割掉(s, u)和(s, v),表明u和v都在核s中运行(注意此处被割掉的边才是我们选择的方案),要么割掉(u, t)和(v, t),此时是不需要割掉(u,v)边的(因为割完之后u和v必定同属一个集合),那么这个情形下我们的开销就只有割掉两条模块与核之间的边所产生的开销
下面考虑情形2,既然u和v不在同一个核,不妨假设割掉(s, u)还有(v, t),按道理来说,割掉之后u应该在T集合里面,v应该在S集合中,但是此时我们会惊讶的发现,由于仍然存在(u, v)和(v, u),即u和v仍然联通,因此需要割掉他们两个的边,也就是附加额外的开销,而这正是题意所说的“两个模块在不同核心上运行的额外开销”。
至此,该问题就能够和最小割联系起来了。
需要注意的两个细节:
1.在添加u和v的边时,请务必两个方向都加边,这是因为在添加增广路时,两个方向都可能添加,否则会WA。
2.使用bfs按层次添加增广路,否则会T。
AC代码送上
```cpp
//Dual Core CPU
//网络流建模 最小割
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;

const int maxn = 2E4+10;
const int maxm = 9E5+10;
int n, m, s, t;

int head[maxn], edge[maxm], ne[maxm], cost[maxm], idx = 2;
void add(int u, int v, int w)//有权图加边
{
    edge[idx] = v;
    cost[idx] = w;
    ne[idx] = head[u];
    head[u] = idx;
    idx++;
}

int dep[maxn];
queue<int> q;
bool bfs()
{
    memset(dep, 0, sizeof dep);
    q.push(s);
    dep[s] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int i = head[u]; i; i = ne[i])
        {
            int v = edge[i];
            if(!dep[v] && cost[i])
            {
                dep[v] = dep[u] + 1;
                q.push(v);
            }
        }
    }
    return dep[t];
}

int dfs(int u, int in)
{
    if(u == t)  return in;
    int out = 0;
    for(int i = head[u]; i; i = ne[i])
    {
        int v = edge[i];
        if(dep[v] == dep[u] + 1 && cost[i])
        {
            int res = dfs(v, min(in, cost[i]));
            cost[i] -= res;
            cost[i^1] += res;
            in -= res;
            out += res;
        }
    }
    if(!out)
        dep[u] = 0;
    return out;
}
int main()
{
    cin >> n >> m;
    s = 0, t = n + 1;
    for(int i = 1; i <= n; ++i)
    {
        int A, B;
        scanf("%d %d", &A, &B);
        add(s, i, A);
        add(i, s, 0);
        add(i, t, B);
        add(t, i, 0);
    }
    while(m--)
    {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        add(u, v, w);
        add(v, u, w);
    }
    int ans = 0;
    while(bfs())
        ans += dfs(s, 0x3f3f3f3f);
    cout << ans << endl;
    return 0;
}
```

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator