zoukankan      html  css  js  c++  java
  • 为了博多

    P2414 - 为了博多

    Description

    做了个噩梦,梦见我的 n 把刀到60级会二次变身,变成一个 对推6图有xi点贡献,刷大阪城有yi点贡献 的刀,于是要把刀分成两队一队刷大阪城另一队推6图 。
    但是有m对兄弟刀在同一队会有特殊的buff加成,加成值为wi,问怎样分队收益最大,最大值是多少。

    Input

    第一行两个整数n(刀的数目)(0<=n<=20000),m(兄弟刀的对数)(0<=m<=200000)
    接下来n行,每行两个整数xi,yi,分别表示第i把刀对推6图的贡献xi和对刷大阪城的贡献yi。
    接下来m行,每行三个整数u,v,wi,分别表示第u把刀和第v把刀是兄弟刀,在一队能产生wi的buff值。

    Output

    一行一个数字,表示最大收益

    Sample Input

    3 1
    1 10
    2 10
    10 3
    2 3 1000

    Sample Output

    1023

    A作为源点,B作为汇点。
    每把刀与A连一条,B连一条。
    兄弟刀直接连一条。
    然后跑最大流,总权值-最小割就是答案。
    其实这个问题的模型就是二分图点权最大独立集(其实并没有二分图)。
    因为对于每一把刀,只能放到A或B,每一对兄弟刀,要么都放到A,要么都放到B,要么不组合在一起,所以求出最小割就可以了。

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<ctime>
     6 #include<cmath>
     7 #include<string>
     8 #include<vector>
     9 #include<cstdio>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define maxn 20010
    15 #define maxm 200010
    16 #define inf 199999999999
    17 #define LL long long
    18 using namespace std;
    19 struct data{
    20   int nex,to;
    21   LL w;
    22 }e[maxn*6+maxm*4];
    23 int head[maxn*2+maxm*2],edge=-1,lev[maxn*2+maxm*2];
    24 void add(int from,int to,LL w){
    25   e[++edge].nex=head[from];
    26   e[edge].to=to;
    27   e[edge].w=w;
    28   head[from]=edge;
    29 }
    30 inline bool bfs(int s,int t){
    31   queue<int>q;
    32   q.push(s);
    33   memset(lev,0,sizeof(lev));
    34   lev[s]=1;
    35   while(!q.empty()){
    36     int u=q.front();
    37     q.pop();
    38     for(int i=head[u];i!=-1;i=e[i].nex)
    39       if(e[i].w>0 && !lev[e[i].to]){
    40     lev[e[i].to]=lev[u]+1;
    41     q.push(e[i].to);
    42     if(e[i].to==t)return 1;
    43       }
    44   }
    45   return 0;
    46 }
    47 LL dfs(int s,int t,LL k){
    48   if(s==t) return k;
    49   LL tag=0;
    50   for(int i=head[s];i!=-1;i=e[i].nex)
    51     if(e[i].w>0 && lev[e[i].to]==lev[s]+1){
    52       int d=dfs(e[i].to,t,min(k-tag,e[i].w));
    53       e[i].w-=d;
    54       e[i^1].w+=d;
    55       tag+=d;
    56       if(tag==k) return tag;
    57     }
    58   return tag;
    59 }         
    60 LL dinic(int s,int t){
    61   LL flow=0;
    62   while(bfs(s,t)) flow+=dfs(s,t,inf);
    63   return flow;
    64 }
    65 int main()
    66 {
    67   freopen("!.in","r",stdin);
    68   freopen("!.out","w",stdout);
    69   int n,m,x,y,z;
    70   LL tot1=0,tot2=0;
    71   scanf("%d%d",&n,&m);
    72   memset(head,-1,sizeof(head));
    73   int s=0,t=n+1;
    74   for(int i=1;i<=n;i++)
    75     scanf("%d%d",&x,&y),add(s,i,x),add(i,s,0),add(i,t,y),add(t,i,0),tot1+=x+y;
    76   for(int i=1;i<=m;i++)
    77     scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,0),add(y,x,z),add(x,y,0),tot2+=z;
    78   printf("%lld",tot1-dinic(s,t)+tot2);
    79   return 0;
    80 }
    
    
    
    
    
  • 相关阅读:
    go语言学习---指针
    vscode打开多个窗口配置
    python网页版编辑器jupyter使用教程
    go语言学习---判断链表是否有环
    go语言学习---二分查找
    go语言学习---反转链表
    cvxpy学习---初识&&安装使用
    redis学习---linux源码搭建安装redis
    javaScript中的空值和假值
    nrm是什么?以及nrm的安装与命令
  • 原文地址:https://www.cnblogs.com/pantakill/p/6613407.html
Copyright © 2011-2022 走看看