• [hdu 4307]Matrix


    真是一道很好的题目喵~

    一看题面真是无语了……很直接、很暴力、很恶心。说实话,除了 straight forward 我脑子里就没想过别的

    上网看了一下居然是最小割,脑子里面一下子就清醒了,N<=1000 而且 A[i]=0 or 1 的,似乎数据上具备了网络流的前提~

    现在来看一看那个公式:

    稍微变一变:

    这样就非常明显了,要最大化 D 的值,就要最小化后面括号里的表达式

    而表达式的值仅和 ai 的值有关,可以视为:

    若取 ai=0 时,要付出 ∑bij 的代价,若取 ai=1,则要付出 ci 的代价,同时,若  ai=1 且  aj=0 ,则又要付出 bij 的代价,问最小代价

    这尼玛经典的最小割,建立源点 S 汇点 T ,令 ai 向 S 和 T 连边,若 ai 最终与 S 相连则 ai=1,否则 ai=0,再在 ai 和 aj 间连一条边,表示若 ai 和 aj 最后分属不同集合,则需付出 bij 的代价

    然后,这道题就被 AC 了……

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #define min(x, y) ((x)<(y) ? (x):(y))
      5 const int inf=0x7FFFFFFF;
      6 const int sizeOfPoint=1024;
      7 const int sizeOfEdge=33554432;
      8 
      9 int cases;
     10 int N;
     11 int S, T;
     12 int B[sizeOfPoint][sizeOfPoint], Bi[sizeOfPoint], C[sizeOfPoint];
     13 int h[sizeOfPoint];
     14 inline int getint();
     15 inline void putint(int);
     16 
     17 struct edge {int point, flow; edge * next, * pair;};
     18 edge memory[sizeOfEdge], * port=memory;
     19 edge * e[sizeOfPoint];
     20 inline void clear() {port=memory; memset(e, 0, sizeof e);}
     21 inline edge * newedge(int point, int flow, edge * next)
     22 {
     23     edge *  ret=port++;
     24     ret->point=point; ret->flow=flow; ret->next=next;
     25     return ret;
     26 }
     27 inline void link(int u, int v, int f)
     28 {
     29     e[u]=newedge(v, f, e[u]); e[v]=newedge(u, 0, e[v]);
     30     e[u]->pair=e[v]; e[v]->pair=e[u];
     31 }
     32 inline bool bfs();
     33 inline int aug();
     34 inline int dinic();
     35 
     36 int main()
     37 {
     38     int ans;
     39 
     40     for (cases=getint();cases;cases--)
     41     {
     42         clear();
     43         N=getint();
     44         memset(Bi, 0, sizeof Bi);
     45         for (int i=1;i<=N;i++)
     46             for (int j=1;j<=N;j++)
     47                 Bi[i]+=(B[i][j]=getint());
     48         for (int i=1;i<=N;i++)
     49             C[i]=getint();
     50         ans=0;
     51         for (int i=1;i<=N;i++) ans+=Bi[i];
     52 
     53         S=0; T=N+1;
     54         for (int i=1;i<=N;i++)
     55             link(S, i, Bi[i]),
     56             link(i, T, C[i]);
     57         for (int i=1;i<=N;i++)
     58             for (int j=1;j<=N;j++) if (i!=j)
     59                 link(i, j, B[i][j]);
     60         ans-=dinic();
     61         putint(ans);
     62     }
     63 
     64     return 0;
     65 }
     66 inline int getint()
     67 {
     68     register int num=0;
     69     register char ch;
     70     do ch=getchar(); while (ch<'0' || ch>'9');
     71     do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
     72     return num;
     73 }
     74 inline void putint(int num)
     75 {
     76     char stack[15];
     77     register int top=0;
     78     if (num==0) stack[top=1]='0';
     79     for ( ;num;num/=10) stack[++top]=num%10+'0';
     80     for ( ;top;top--) putchar(stack[top]);
     81     putchar('
    ');
     82 }
     83 inline bool bfs()
     84 {
     85     static int q[sizeOfPoint];
     86     int l=0, r=0;
     87     memset(h, 0xFF, sizeof h); h[T]=0;
     88     for (q[r++]=T;l<r;l++)
     89     {
     90         int u=q[l];
     91         for (edge * i=e[u];i;i=i->next) if (i->pair->flow && h[i->point]==-1)
     92             h[q[r++]=i->point]=h[u]+1;
     93     }
     94     return h[S]>=0;
     95 }
     96 inline int aug()
     97 {
     98     static edge * t[sizeOfPoint], * path[sizeOfPoint];
     99     static int aug[sizeOfPoint];
    100     int flow=0;
    101     memset(aug, 0, sizeof aug); aug[S]=inf;
    102     memset(path, 0, sizeof path);
    103     memmove(t, e, sizeof e);
    104     for (int u=S; ; )
    105     {
    106         if (u==T)
    107         {
    108             flow+=aug[T];
    109             for (edge * i=path[T];i;i=path[i->point])
    110                 i->pair->flow-=aug[T], i->flow+=aug[T], aug[i->point]-=aug[T];
    111             for (edge * i=path[T];i && u==T;i=path[i->point]) if (aug[i->point])
    112                 u=i->point;
    113         }
    114         edge *& i=t[u];
    115         for ( ;i && (!i->flow || h[i->point]+1!=h[u]);i=i->next);
    116         if (i)
    117         {
    118             path[i->point]=i->pair; aug[i->point]=min(aug[u], i->flow);
    119             u=i->point;
    120         }
    121         else
    122         {
    123             if (u==S) break;
    124             h[u]=-1;
    125             u=path[u]->point;
    126         }
    127     }
    128     return flow;
    129 }
    130 inline int dinic()
    131 {
    132     register int flow=0;
    133     for ( ;bfs();flow+=aug());
    134     return flow;
    135 }
    本傻装B系列

    这道题告诉我们,如果要求的是一个最大/小化某个表达式的数组,且每个数字的取值范围都很小时可以考虑用最小割做~

  • 相关阅读:
    mac os x 之通过远程主机在nginx上部署web静态页面
    基于jQuery UI的调色板插件推荐colorpicker
    Mac 访问隐藏文件方法! 网上方法在我电脑上都不可用!
    JavaScript设计模式学习之单例模式
    由一篇博文做出的代码,不用Math.round()如何实现其功能
    mac os x之解决npm安装包失败,或者nodejs工程缺少依赖
    用nginx的反向代理机制解决前端跨域问题
    mac之os x系统下搭建nodejs+express4.x+mongodb+gruntjs整套前端工程
    sourcetree window10 闪退
    滚动条自定义样式
  • 原文地址:https://www.cnblogs.com/dyllalala/p/3991656.html
Copyright © 2020-2023  润新知