网络流测试-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

原文地址:https://www.cnblogs.com/shzr/p/10599196.html