[BZOJ1322]Destroying The Graph

题目大意:
有一张有向图,对于每个点,有两种操作:
1. 删掉它的所有入边
2. 删掉它的所有出边
对每个点的每个操作均有不同的价值。
求使得图上没有边的最小价值。
解题思路:
考虑把点拆成入点和出点,然后就是二分图最小点权覆盖集。
也可以考虑最小割。
从S到每个点的入点连容量为该点执行操作2的价值,每个点的出点到T连容量为该点执行操作1的价值。对于图上的每条边连容量inf的边。
然后答案就是最小割(割一条S出发的边,相当于执行了2操作,网络流不可能从该点再流向其他节点,则相当于删掉出边。操作1同理)。

C++ Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<bits/stdc++.h>
using namespace std;
const int S=0,T=10005,inf=0x3fffffff;
struct edge{
    int to,nxt,cap;
}e[200005];
int head[10050],cnt=1,n,m,level[10050],iter[10050];
inline void addedge(int from,int to,int flow){
    e[++cnt]=(edge){to,head[from],flow};
    head[from]=cnt;
    e[++cnt]=(edge){from,head[to],0};
    head[to]=cnt;
}
queue<int>q;
void bfs(){
    level[S]=1;
    for(q.push(S);!q.empty();){
        int u=q.front();
        q.pop();
        for(int i=head[u];~i;i=e[i].nxt)
        if(e[i].cap&&!~level[e[i].to]){
            level[e[i].to]=level[u]+1;
            q.push(e[i].to);
        }
    }
}
inline int min(int a,int b){return a<b?a:b;}
int dfs(int u,int f){
    if(!f||u==T)return f;
    for(int& i=iter[u];~i;i=e[i].nxt)
    if(e[i].cap&&level[e[i].to]>level[u]){
        int d=dfs(e[i].to,min(f,e[i].cap));
        if(d){
            e[i].cap-=d;
            e[i^1].cap+=d;
            return d;
        }else level[e[i].to]=-1;
    }
    return 0;
}
int dinic(){
    for(int flow=0,f;;){
        memset(level,-1,sizeof iter);
        if(bfs(),!~level[T])return flow;
        memcpy(iter,head,sizeof iter);
        while(f=dfs(S,inf))flow+=f;
    }
}
int main(){
    memset(head,-1,sizeof head);
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        int p;
        cin>>p;
        addedge(i+n,T,p);
    }
    for(int i=1;i<=n;++i){
        int p;
        cin>>p;
        addedge(S,i,p);
    }
    while(m--){
        int x,y;
        cin>>x>>y;
        addedge(x,y+n,inf);
    }
    cout<<dinic()<<endl;
    return 0;
}

 

posted @   Mrsrz  阅读(123)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
历史上的今天:
2017-07-13 [BZOJ4373]算术天才⑨与等差数列
点击右上角即可分享
微信分享提示