网络流测试-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\n",ans);
154     }
155     return 0;
156 }

game

---shzr

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

时间: 2024-11-08 12:17:10

网络流测试-2019.3.24的相关文章

2019.7.24 校内测试 分析+题解

T1 地雷 题目很简单呢,就是求哪个数只出现了一次就可以了哦~ 我一开始的想法是桶排(这也是最单纯最简单的想法吧~),但是空间开 232 肯定会炸的,而且时间好像也会炸掉. 然后左边的 ych 大佬小声说了一句:“得换个算法.” 嗯,确实要换个算法,然后我就觉得新算法一定是不用开数组,直接输完数据就能出答案的那种! 然后不知道怎么就想到了 zhx 讲博弈论的时候输入的同时将 ……(一些稀奇古怪的东西) 异或起来就是答案,这不正好跟我理想的新算法很像嘛? 异或异或?咦,又想到了六月底那次考试有个叫

数据结构测试1 on 2019.9.24

T1 union 一开始我被这个题目带进去了,以为真的是并查集,但实际上此题与并查集毫无半毛钱关系. 其实我们可以先离线建好所有的图,然后把建边的时间作为他们的边权.因为两个点什么时候联通取决于它们路径上的点最晚的链接时间,也就是最大边权.而题目明摆了是一棵树,所有考虑树剖维护边权和查询最大值. 代码如下: #include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; struct node{ int nxt,to,val

PAT 甲级 A1042 (2019/01/24)

1 #include <cstdio> 2 const int N = 54; 3 char Color[5] = {'S', 'H', 'C', 'D', 'J'}; 4 int start[N+1], trans[N+1], end[N+1]; 5 int main() { 6 int n; 7 scanf("%d",&n); 8 for(int i = 1; i <= N; i++){ 9 start[i] = i; 10 } 11 for(int i

2019.9.24 网络ip小知识

原文链接:https://blog.csdn.net/faker_wang/article/details/80747407 :https://www.cnblogs.com/wktwj/p/10862618.html 摘抄一些我觉得比较需要知道的东西吧 子网掩码: 子网掩码(subnet mask)又叫网络掩码.地址掩码.子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码. 子网掩码不能单独存在,它必须结合IP地址一起使用.子网掩码只有一个作

梦想MxWeb3D协同设计平台 2019.01.24更新

SDK开发包下载地址:http://www.mxdraw.com/ndetail_10124.html1.  编写快速入门教程2.  重构前端代码,支持一个页面多个三维控件同时加载,或二维和三维同时加载 3.  简化前端代码引用控件,只需一个函数就能动态创建三维控件4. 三维控件绘图区域,与界面UI分离5. 二维增加交互绘图接口6. 导出三维建模函数和三维运算函数提供了使用js开发的调用演示例程7. 增加导出二维图纸.遍历.对象查询.修改.绘图等函数 原文地址:https://www.cnblo

2019.03.24后台站点

1.后台站点和admin.py与模型相关联 在admin.py中添加admin.site.register(Clazz) 2.Python manage.py createsuperuser 3.在setting中修改成中文  'zh-Hans' 'Asia/Shanghai' false 4.修改第一个标题  在apps.py中添加 verbose_name = u'学生应用' 然后在init中添加这个, default_app_config = 'stu.apps.StulConfig' 原

2019.03.24 表单类

Form.form是一种内置的模板吧,它有自己设置的表单样式 可以引用它,但我觉得还是自己写会比较好吧 继承的是forms类了而不是models类了 然后就是表单得验证,也是用了内置得数据库叫做 authenticate,login就是存admin密码的那个 概述 表单既可以在模板页面利用HTML编写,也可以使用Django提供的表单类编写. 相关属性参考官网:https://docs.djangoproject.com/en/1.11/ref/forms/fields/ 实现熟悉的用户登录功能

蒟蒻总结-2019.3.24

草草写完的,写的不太好,望谅解 移动"哨兵棋子" 题面+数据规模 一条数轴有\(N\)个棋子,每个棋子可以占据一个整数位置.\(N\)个棋子目前位于不同的整数位置,现在你想要移动它们以便它们占据N个连续位置(例如,位置\(5,6,7,8\)).当前所有棋子中位置最小或者位置最大的棋子,称为"哨兵棋子".每一次,你只能移动"哨兵棋子".你可以把"哨兵棋子"移动到当前任何未占用的整数位置,前提是在这个新位置该棋子不再是一个&quo

2019.4.24(js)

1. 取得正数和负数的绝对值 Math.abs(7.25) Math.abs(-7.25) 2.利用JS刷新页面方法 https://www.cnblogs.com/Chen-XiaoJun/p/6219880.html 1 //刷新当前窗口 2 window.location.href=window.location.href; 3 window.location.reload; 对于刷新父页面的如下: 1 //刷新父页面 2 window.opener.location.href=windo