【xsy1232】Magic 最小割

题目大意:给你一个$n$个点,$m$条有向边的图,每个点有一个点权$a_i$,同时你可以用$b_i$的代价将$a_i$变为$0$

另外你要付出$sumlimits_{i=1}^nmaxlimits_{(i,j)}a_j$这么多代价。请最小化代价。

数据范围:$n≤1000$,$m≤50000$。

貌似是一道套路最小割

把每个点拆成两个点,对每条边新建一个点,将一个点的出边按终点的$a$从大到小排序后建图如下


该建图方式,只有让某个前缀$a_i$全部变为$0$,一个点产生的费用才会改变,这个建图保证了如果要割$a_i$就必须要割掉$b_1$至$b_{i-1}$,且不会割掉两个$a$

我们对每个点都这么建一波,然后跑个最大流就没了

orzlyy!!!!!

 1 #include<bits/stdc++.h>
 2 #define M 60005
 3 #define INF (1<<30)
 4 using namespace std;
 5 
 6 struct edge{int u,v,next;}e[M*4]={0}; int head[M]={0},use=0;
 7 void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
 8 void Add(int x,int y,int z){add(x,y,z); add(y,x,0);}
 9 int dis[M]={0},S,T; queue<int> q;
10 bool bfs(){
11     memset(dis,0,sizeof(dis));
12     dis[S]=1; q.push(S);
13     while(!q.empty()){
14         int u=q.front(); q.pop();
15         for(int i=head[u];~i;i=e[i].next)
16         if(dis[e[i].u]==0&&e[i].v){
17             dis[e[i].u]=dis[u]+1;
18             q.push(e[i].u);
19         }
20     }
21     return dis[T];
22 }
23 int dfs(int x,int flow){
24     if(x==T) return flow; int sum=0;
25     for(int i=head[x];~i;i=e[i].next)
26     if(dis[x]+1==dis[e[i].u]&&e[i].v){
27         int k=dfs(e[i].u,min(flow,e[i].v));
28         sum+=k; flow-=k; 
29         e[i].v-=k; e[i^1].v+=k;
30         if(flow==0) return sum;
31     }
32     if(sum==0) dis[x]=-1;
33     return sum;
34 }
35 int dinic(){
36     int res=0;
37     while(bfs()) 
38     res+=dfs(S,INF);
39     return res;
40 }
41 
42 int n,m,a[M]={0},b[M]={0};
43 vector<int> g[M];
44 bool cmp(int x,int y){return a[x]>a[y];}
45 void ReadData(){
46     memset(head,-1,sizeof(head));
47     scanf("%d%d",&n,&m);
48     for(int i=1;i<=n;i++) scanf("%d",a+i);
49     for(int i=1;i<=n;i++) scanf("%d",b+i);
50     for(int i=1;i<=m;i++){
51         int x,y; scanf("%d%d",&x,&y);
52         g[x].push_back(y);// g[y].push_back(x);
53     }
54 }
55 void build(){
56     S=0; T=2*n+1; int N=2*n+1;
57     for(int i=1;i<=n;i++) Add(S,i,INF);
58     for(int i=1;i<=n;i++) Add(i+n,T,b[i]);
59     for(int x=1;x<=n;x++){
60         sort(g[x].begin(),g[x].end(),cmp);
61         for(int i=0;i<g[x].size();i++){
62             N++;
63             Add(i?N-1:x,N,a[g[x][i]]);
64             Add(N,n+g[x][i],INF);
65         }
66     }
67 }
68 int main(){
69     ReadData();
70     build();
71     cout<<dinic()<<endl;
72 }
原文地址:https://www.cnblogs.com/xiefengze1/p/10395684.html