zoukankan      html  css  js  c++  java
  • 网络流测试-2019.3.24

    网络流专题测试-2019.03.24

      24号的考试了,但是一直忘了写,今天来补一补。

      defuze:http://hzwer.com/6009.html

      不想写题面了,直接说怎么做吧。

      其实这道题可以直接用最普通的费用流来做,找增广路时把spfa的比较函数改改就行了,但是我没想到。

      可以对概率取对数,转成加法再做,就非常简单了。

      注意:找增广路时设置一个精度,如果两条路径的差小于精度,就不进行松弛。否则可能会在几条费用极其相似的道路上反复增广导致超时。

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <cmath>
     4 # include <cstring>
     5 # include <queue>
     6 # define R register int
     7 
     8 using namespace std;
     9 
    10 const int maxn=105;
    11 const double eps=1e-7;
    12 const int inf=1e9;
    13 int s,t,n,m,k,h=1,firs[maxn],pre[maxn],Fl[maxn],in_que[maxn];
    14 double d[maxn],x,ans;
    15 struct edge
    16 {
    17     int too,nex,cap;
    18     double co;
    19 }g[maxn*maxn];
    20 queue <int> q;
    21 
    22 void add (int x,int y,int cap,double co)
    23 {
    24     g[++h].nex=firs[x];
    25     firs[x]=h;
    26     g[h].too=y;
    27     g[h].cap=cap;
    28     g[h].co=co;
    29     g[++h].nex=firs[y];
    30     firs[y]=h;
    31     g[h].too=x;
    32     g[h].cap=0;
    33     g[h].co=-co;
    34 }
    35 
    36 bool bfs()
    37 {
    38     for (R i=0;i<=t;++i) d[i]=-inf;
    39     double fg=d[0];
    40     q.push(s); Fl[s]=inf; d[s]=0;
    41     int beg,j;
    42     while(q.size())
    43     {
    44         beg=q.front(); q.pop();
    45         in_que[beg]=0;
    46         for (R i=firs[beg];i;i=g[i].nex)
    47         {
    48             j=g[i].too;
    49             if(g[i].cap<=0) continue;
    50             if(d[j]+eps>=d[beg]+g[i].co) continue;
    51             d[j]=d[beg]+g[i].co;
    52             pre[j]=i; Fl[j]=min(Fl[beg],g[i].cap);
    53             if(!in_que[j]) q.push(j),in_que[j]=true;
    54         }
    55     }
    56     return (d[t]!=fg);
    57 }
    58 
    59 void dfs()
    60 {
    61     int x=t,i;
    62     while(x!=s)
    63     {
    64         i=pre[x];
    65         g[i].cap-=Fl[t];
    66         g[i^1].cap+=Fl[t];
    67         x=g[i^1].too;
    68     }
    69     ans+=d[t]*Fl[t];
    70 }
    71 
    72 int main()
    73 {
    74     scanf("%d%d%d",&m,&n,&k);
    75     s=0,t=n+m+1;
    76     for (R i=1;i<=n;++i) add(s,i,1,0);
    77     for (R i=1;i<=m;++i) add(i+n,t,k,0);
    78     for (R i=1;i<=m;++i)
    79         for (R j=1;j<=n;++j)
    80         {
    81             scanf("%lf",&x);
    82             add(j,i+n,1,log(x));
    83         }
    84     while(bfs())
    85         dfs();
    86     printf("%.4lf",exp(ans));
    87     return 0;
    88 }
    defuze

      Asiram:http://hzwer.com/6012.html

      其实就是一个最大密度子图的板子题,但是只听过没写过,而且还读错了题,爆零了。具体做法可能会在专门讲网络流那篇blog里面讲讲,也可能会咕咕咕。

      
      1 # include <cstdio>
      2 # include <iostream>
      3 # include <cmath>
      4 # include <cstring>
      5 # include <queue>
      6 # define R register int
      7 # define ll long long
      8 
      9 using namespace std;
     10 
     11 const int maxn=502;
     12 const int maxm=5003;
     13 const ll inf=1e15;
     14 int n,m,a[maxm],b[maxm],firs[maxn+maxm],h=1,cur[maxn+maxm],d[maxn+maxm],vis[maxn+maxm];
     15 ll w[maxn],v[maxm];
     16 int s,t;
     17 queue <int> q;
     18 struct edge
     19 {
     20     int too,nex; ll cap;
     21 }g[40000];
     22 
     23 void add (int x,int y,ll cap)
     24 {
     25     g[++h].nex=firs[x];
     26     firs[x]=h;
     27     g[h].too=y;
     28     g[h].cap=cap;
     29     g[++h].nex=firs[y];
     30     firs[y]=h;
     31     g[h].too=x;
     32     g[h].cap=0;
     33 }
     34 
     35 bool bfs ()
     36 {
     37     memset(vis,0,sizeof(vis));
     38     q.push(s); vis[s]=1;
     39     int beg,j;
     40     while(q.size())
     41     {
     42         beg=q.front();
     43         q.pop();
     44         for (R i=firs[beg];i;i=g[i].nex)
     45         {
     46             j=g[i].too;
     47             if(g[i].cap<=0) continue;
     48             if(vis[j]) continue;
     49             vis[j]=1; d[j]=d[beg]+1;
     50             q.push(j);
     51         }
     52     }
     53     return vis[t];
     54 }
     55 
     56 ll dfs (int x,ll minf)
     57 {
     58     if(x==t||minf==0) return minf;
     59     int j; ll f,flow=0;
     60     for (R &i=cur[x];i;i=g[i].nex)
     61     {
     62         j=g[i].too;
     63         if(d[x]+1!=d[j]) continue;
     64         f=dfs(j,min(minf,g[i].cap));
     65         if(f<=0) continue;
     66         flow+=f; minf-=f;
     67         g[i].cap-=f; g[i^1].cap+=f;
     68         if(minf==0) break;
     69     }
     70     return flow;
     71 }
     72 
     73 ll Dinic()
     74 {
     75     ll ans=0;
     76     while(bfs())
     77     {
     78         for (R i=0;i<=t;++i) cur[i]=firs[i];
     79         ans+=dfs(s,inf);
     80     }
     81     return ans;
     82 }
     83 
     84 bool check (ll x)
     85 {
     86     ll ans=0;
     87     memset(firs,0,sizeof(firs)); h=1; t=n+m+1;
     88     for (R i=1;i<=n;++i) add(i+m,t,x*w[i]);
     89     for (R i=1;i<=m;++i) add(s,i,v[i]),ans+=v[i];
     90     for (R i=1;i<=m;++i) add(i,a[i]+m,inf),add(i,b[i]+m,inf);
     91     if(Dinic()<ans) return true; return false;
     92 }
     93 
     94 int main()
     95 {
     96     scanf("%d%d",&n,&m);
     97     for (R i=1;i<=n;++i) scanf("%lld",&w[i]);
     98     for (R i=1;i<=m;++i)
     99         scanf("%d%d%lld",&a[i],&b[i],&v[i]),v[i]*=10000000;
    100     ll l=1,r=1e9,mid,ans;
    101     while(l<=r)
    102     {
    103         mid=(l+r)>>1;
    104         if(check(mid)) ans=mid,l=mid+1;
    105         else r=mid-1;
    106     }
    107     printf("%.7lf",(double)ans/10000000);
    108     return 0;
    109 }
    Asiram

      game:https://www.lydsy.com/JudgeOnline/problem.php?id=2756

      考试的想了很久这道题,本来以为一定能A的,结果被多组数据坑掉了40分。为什么?因为没清空数组...

      首先,如果确定了最后改到多大,那么就将每个点要加的次数作为点权,黑白染色一下,跑一遍带权最大匹配,满流则说明有解。

      那么问题转化为了如何找这个最大值。

      一个显然的结论是,对于格子数为偶数的棋盘,如果M是一个可行的最终值,那么M+1也是一个可行的最终值;所以对于格子数为偶数的棋盘,可以二分这个最大值。对于格子数为奇数的棋盘,不满足以上性质。

      如果想要满流,一个最基本的条件是左右两部的流量相等。对于格子数为奇数的棋盘,奇偶格子的数量不同,所以说:如果最大值为M时,奇格子总共要加a次,偶格子总共要加b次,那么当最大值改变后,a-b的值也会随之发生改变。当a-b等于0时,才“有可能”满足要求。所以M可以直接算出来。注意:M不能比格子中的最大数小。

      
      1 # include <cstdio>
      2 # include <iostream>
      3 # include <cmath>
      4 # include <cstring>
      5 # include <queue>
      6 # define R register int
      7 # define ll long long
      8 
      9 using namespace std;
     10 
     11 const int maxn=1703;
     12 const ll inf=1e15;
     13 int T,n,m,d[maxn],cnt,h=1,firs[maxn],vis[maxn],s,t,cur[maxn],id[maxn][maxn];
     14 ll ans,a[41][41],mx,b[41][41];
     15 struct edge
     16 {
     17     int too,nex;
     18     ll cap;
     19 }g[17004];
     20 queue <int> q;
     21 
     22 void add (int x,int y,ll cap)
     23 {
     24     g[++h].nex=firs[x];
     25     firs[x]=h;
     26     g[h].too=y;
     27     g[h].cap=cap;
     28     g[++h].nex=firs[y];
     29     firs[y]=h;
     30     g[h].too=x;
     31     g[h].cap=0;
     32 }
     33 
     34 bool bfs ()
     35 {
     36     memset(vis,0,sizeof(vis));
     37     q.push(s); vis[s]=1; d[s]=0;
     38     int beg,j;
     39     while(q.size())
     40     {
     41         beg=q.front();
     42         q.pop();
     43         for (R i=firs[beg];i;i=g[i].nex)
     44         {
     45             j=g[i].too;
     46             if(g[i].cap<=0) continue;
     47             if(vis[j]) continue;
     48             vis[j]=1; d[j]=d[beg]+1;
     49             q.push(j);
     50         }
     51     }
     52     return vis[t];
     53 }
     54 
     55 ll dfs (int x,ll minf)
     56 {
     57     if(x==t||minf==0) return minf;
     58     int j; ll f,flow=0;
     59     for (R &i=cur[x];i;i=g[i].nex)
     60     {
     61         j=g[i].too;
     62         if(d[x]+1!=d[j]) continue;
     63         f=dfs(j,min(minf,g[i].cap));
     64         if(f<=0) continue;
     65         flow+=f; minf-=f;
     66         g[i].cap-=f; g[i^1].cap+=f;
     67         if(minf==0) break;
     68     }
     69     return flow;
     70 }
     71 
     72 ll Dinic()
     73 {
     74     ll ans=0;
     75     while(bfs())
     76     {
     77         for (R i=0;i<=t;++i) cur[i]=firs[i];
     78         ans+=dfs(s,inf);
     79     }
     80     return ans;
     81 }
     82 
     83 ll check (ll mx)
     84 {
     85     memset(firs,0,sizeof(firs));
     86     h=1;
     87     ll ans=0,max_flow; 
     88     for (R i=1;i<=n;++i)
     89         for (R j=1;j<=m;++j)
     90         {
     91             a[i][j]=mx-b[i][j];
     92             if((i+j)%2)
     93             {
     94                 ans+=a[i][j];
     95                 add(s,id[i][j],a[i][j]);
     96                 if(id[i+1][j]) add(id[i][j],id[i+1][j],inf);
     97                 if(id[i][j+1]) add(id[i][j],id[i][j+1],inf);
     98             }
     99             else
    100             {
    101                 add(id[i][j],t,a[i][j]);
    102                 if(id[i+1][j]) add(id[i+1][j],id[i][j],inf);
    103                 if(id[i][j+1]) add(id[i][j+1],id[i][j],inf);
    104             }
    105         }
    106     max_flow=Dinic();
    107     if(max_flow==ans) return ans;
    108     return -1;    
    109 }
    110 
    111 int main()
    112 {
    113     scanf("%d",&T);
    114     while(T--)
    115     {
    116         scanf("%d%d",&n,&m);
    117         mx=0;
    118         s=0,t=n*m+1;
    119         ans=0; cnt=0;
    120         memset(id,0,sizeof(id));
    121         for (R i=1;i<=n;++i)
    122             for (R j=1;j<=m;++j)
    123             {
    124                 id[i][j]=++cnt;
    125                 scanf("%lld",&b[i][j]);
    126                 mx=max(b[i][j],mx);
    127             }
    128         ll t1=0,t2=0;
    129         for (R i=1;i<=n;++i)
    130             for (R j=1;j<=m;++j)
    131                 if((i+j)%2) t2+=mx-b[i][j];
    132                 else t1+=mx-b[i][j];
    133         if(n*m%2)
    134         {
    135             if(t2<t1) { puts("-1"); continue; }
    136             mx+=t2-t1;
    137             ans=check(mx);
    138         }
    139         else
    140         {
    141             ll l=mx,r=mx+1e9,mid,t; ans=-1;
    142             if(t1!=t2) { puts("-1"); continue; }
    143             while(l<=r)
    144             {
    145                 mid=(l+r)>>1;
    146                 t=check(mid);
    147                 if(t!=-1) r=mid-1;
    148                 else l=mid+1;
    149                 if(t==-1) continue;
    150                 if(ans==-1) ans=t; else ans=min(ans,t);
    151             }
    152         }
    153         printf("%lld
    ",ans);
    154     }    
    155     return 0;
    156 }
    game

    ---shzr

  • 相关阅读:
    ubuntu18.04英文环境解决各种软件中文乱码问题
    Centos6两个镜像文件的合并方法
    将centos的yum源修改为阿里云的yum源
    Linux TOP 命令总结
    Nginx add SSL 证书 基础配置
    Nginx Http 核心模块中Server Location 配置
    df -h执行卡住不动问题解决
    Jetty Session Persistence By Redis
    Spring @Transactional配置知识梳理
    通用FTP Client模块设计与实现
  • 原文地址:https://www.cnblogs.com/shzr/p/10599196.html
Copyright © 2011-2022 走看看