zoukankan      html  css  js  c++  java
  • loj6045 「雅礼集训 2017 Day8」价

    我们考虑最小割。

    我一开始觉得是裸的最小割,就直接S到每个减肥药连up+p[i]的边,减肥药到药材连inf边,药材到T连up,然后得到了40分的好成绩。

    之后我发现这是一个假的最小割,最小割割的是代价或者得不到的收益,上面说的这种建图左边割掉的是收益,右边割掉的是代价,然后当然就gg了。

    所以我们把p取相反数,因为有负权,我们在给所有边加上一个UP,之后就可以直接建图最小割了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #define UP 2000000
     8 #define inf 0x7fffffff
     9 #define N 666
    10 using namespace std;
    11 int e=2,head[N];
    12 struct edge{
    13     int u,v,f,next;
    14 }ed[N*N];
    15 void add(int u,int v,int f){
    16     ed[e].u=u;ed[e].v=v;ed[e].f=f;
    17     ed[e].next=head[u];head[u]=e++;
    18     ed[e].u=v;ed[e].v=u;ed[e].f=0;
    19     ed[e].next=head[v];head[v]=e++;
    20 }
    21 int n,ans,S,T,dep[N];
    22 bool bfs(){
    23     memset(dep,0,sizeof dep);
    24     queue<int> q;q.push(S);dep[S]=1;
    25     while(!q.empty()){
    26         int x=q.front();q.pop();
    27         for(int i=head[x];i;i=ed[i].next){
    28             if(ed[i].f&&!dep[ed[i].v]){
    29                 dep[ed[i].v]=dep[x]+1;
    30                 if(ed[i].v==T)return 1;
    31                 q.push(ed[i].v);
    32             }
    33         }
    34     }
    35     return 0;
    36 }
    37 int dfs(int x,int f){
    38     if(x==T||!f)return f;
    39     int ans=0;
    40     for(int i=head[x];i;i=ed[i].next){
    41         if(ed[i].f&&dep[ed[i].v]==dep[x]+1){
    42             int nxt=dfs(ed[i].v,min(f,ed[i].f));
    43             ans+=nxt,f-=nxt;ed[i].f-=nxt,ed[i^1].f+=nxt;
    44             if(!f)break;
    45         }
    46     }
    47     if(!ans)dep[x]=-1;
    48     return ans;
    49 }
    50 int dinic(){
    51     int ans=0;
    52     while(bfs())ans+=dfs(S,inf);
    53     return ans;
    54 }
    55 int main(){
    56     // freopen("test.in","r",stdin);
    57     scanf("%d",&n);
    58     S=2*n+1;T=S+1;
    59     for(int i=1,j,k;i<=n;i++){
    60         scanf("%d",&j);
    61         while(j--){
    62             scanf("%d",&k);
    63             add(i,n+k,inf);
    64         }
    65     }
    66     for(int i=1,x;i<=n;i++){
    67         scanf("%d",&x);
    68         add(S,i,UP-x);
    69         add(n+i,T,UP);
    70         ans-=UP-x;
    71     }
    72     ans+=dinic();
    73     printf("%d
    ",ans);
    74 }
    View Code
  • 相关阅读:
    Visual Studio 和 c# 正则表达式
    程序员DD 《Spring boot教程系列》补充
    c# 多线程编程中AutoResetEvent和ManualResetEvent
    c# 事件和EventManager
    卸载重装Mysql
    c# 语法要点速览
    在高分屏正确显示CHM文件
    ss user-rule自定义规则并硬连接到OneDrive进行自动同步
    利用webmagic获取天猫评论
    使用Selenium对新浪微博模拟登录
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8805056.html
Copyright © 2011-2022 走看看