• 【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 }
  • 相关阅读:
    PHP识别验证码-image-ocr
    Session的一些小疑问
    PHP-webdriver自动化测试完成登录
    大文件日志快速解析入库
    Linux权限说明
    使用python的selenium自动化登录获取cookie
    PHP编码的注释规范
    MySQL主主架构、读写分离搭建学习
    用docker尝试nginx的负载均衡
    lua require
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10395684.html
Copyright © 2020-2023  润新知