POJ 2987 Firing 最大流 网络流 dinic 模板

https://www.cnblogs.com/137shoebills/p/9100790.html

http://poj.org/problem?id=2987

之前写过这道题,码一个dinic的最大流板子。

经典问题,选了一个点就有些点必须选,输出使选出的点的权值和最大的最少点数,并输出该权值和。

建图就是s向权值为正的点连流量为val的边,权值为负的点向t连流量为-val的边,所有的权值和-最大流就是答案。

类似于https://www.cnblogs.com/137shoebills/p/7786985.html

细节是注意流量会爆int

 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<queue>
 7 using namespace std;
 8 #define LL long long
 9 const int maxn=5010;
10 const LL minf=(LL)1e11;
11 int n,m,s,t;
12 LL val[maxn]={};
13 struct nod{
14     int y,next;LL v; 
15 }e[140010];
16 int head[maxn]={},tot=1,dep[maxn]={};
17 queue<int>q;
18 bool vis[maxn]={}; int cnt=0;
19 void init(int x,int y,LL v){
20     e[++tot].y=y;e[tot].v=v;e[tot].next=head[x];head[x]=tot;
21 }
22 int bfs(){
23     q.push(s);
24     memset(dep,0,sizeof(dep));
25     dep[s]=1;
26     while(!q.empty()){
27         int x=q.front();q.pop();
28         for(int i=head[x];i;i=e[i].next){
29             if(e[i].v&&(!dep[e[i].y])){
30                 dep[e[i].y]=dep[x]+1;
31                 q.push(e[i].y);
32             }
33         }
34     }
35     return dep[t];
36 }
37 LL dfs(int x,LL fc){
38     if(x==t)return fc;
39     LL tsn=0;
40     for(int i=head[x];i;i=e[i].next){
41         if(e[i].v&&dep[e[i].y]==dep[x]+1){
42             LL z=dfs(e[i].y,min(fc-tsn,e[i].v));
43             tsn+=z;e[i].v-=z;e[i^1].v+=z;
44             if(tsn==fc)break;
45         }
46     }
47     return tsn;
48 } 
49 LL dinic(){
50     LL tsn=0;
51     while(bfs())tsn+=dfs(s,minf);
52     return tsn;
53 }
54 void getit(int x){
55     if(x==t)return;
56     if(x!=s)++cnt;
57     vis[x]=1;
58     for(int i=head[x];i;i=e[i].next){
59         if(e[i].v&&!vis[e[i].y]){
60             getit(e[i].y);
61         }
62     }
63 }
64 int main(){
65     scanf("%d%d",&n,&m);
66     s=n+1;t=s+1;
67     LL ans=0;
68     for(int i=1;i<=n;++i){
69         scanf("%lld",&val[i]);
70         if(val[i]>=0){init(s,i,val[i]); init(i,s,0); ans+=val[i];}
71         else{init(i,t,-val[i]);init(t,i,0);}
72     }
73     for(int i=1;i<=m;++i){
74         int x,y;
75         scanf("%d%d",&x,&y);
76         init(x,y,minf);init(y,x,0);
77     }
78     ans-=dinic();
79     getit(s);
80     printf("%d ",cnt);
81     printf("%lld\n",ans);
82     return 0;
83 }
View Code

 

posted @ 2019-08-01 16:49  鲸头鹳  阅读(206)  评论(0编辑  收藏  举报