Gym - 102346G Getting Confidence 最小费用最大流
Posted lmcc1108
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym - 102346G Getting Confidence 最小费用最大流相关的知识,希望对你有一定的参考价值。
Gym - 102346G Getting Confidence
题意:n*n的格子,每个格子上有一个数,要求每行每列都只能拿一个数,使得乘积最大,然后输出每列选择的是第几行的数。
如果是加法的话,那么很明显,就是一个网络流。可是,现在是乘法怎么办,很简单,直接取log,那么乘法便转换成了加法,然后就可以建图。
每行每列只能取一个数,就相当于行列是拆开的点,因为需要输出的是列的信息,那么源点向每一列建一条流量为1,费用为0的边,而每一行向汇点建一条流量为1,费用为0的边。
再对于每个格子,每一列向它这一列的格子建一条流量为1,费用为0的点,而每个格子向它所在的行建一条流量为1,费用为-log(格子上的数)的边。
最后跑一遍最小费用最大流,看一下每一列的那条边流量为0
1 #include<cstdio> 2 #include<cmath> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 const int N=2e4+11,M=1e6+11,inf=1e9+7; 7 struct Side{ 8 int v,ne,w; 9 double val; 10 }S[M<<1]; 11 double dis[N]; 12 int n,sn,sb,se,head[N],vis[N],flow[N],lu[N]; 13 void init(){ 14 sn=0; 15 sb=0;se=n*n+2*n+1; 16 for(int i=sb;i<=se;i++) head[i]=-1; 17 } 18 void add(int u,int v,int w,double val){ 19 S[sn].w=w;S[sn].val=val; 20 S[sn].v=v;S[sn].ne=head[u]; 21 head[u]=sn++; 22 } 23 void addE(int u,int v,int w,double val){ 24 add(u,v,w,val);add(v,u,0,-val); 25 } 26 bool spfa(){ 27 queue<int> q; 28 for(int i=sb;i<=se;i++){ 29 dis[i]=inf; 30 vis[i]=0; 31 flow[i]=inf; 32 lu[i]=-1; 33 } 34 dis[sb]=0; 35 vis[sb]=1; 36 q.push(sb); 37 int u,v; 38 while(!q.empty()){ 39 u=q.front();q.pop();vis[u]=0; 40 for(int i=head[u];~i;i=S[i].ne){ 41 v=S[i].v; 42 if(S[i].w>0&&dis[v]>dis[u]+S[i].val){ 43 lu[v]=i; 44 dis[v]=dis[u]+S[i].val; 45 flow[v]=min(flow[u],S[i].w); 46 if(!vis[v]){ 47 vis[v]=1; 48 q.push(v); 49 } 50 } 51 } 52 } 53 return dis[se]!=inf; 54 } 55 void mfml(){ 56 int ans=0,ansc=0; 57 while(spfa()){ 58 ans+=flow[se]; 59 ansc+=flow[se]*dis[se]; 60 for(int i=lu[se];~i;i=lu[S[i^1].v]){ 61 S[i].w-=flow[se]; 62 S[i^1].w+=flow[se]; 63 } 64 } 65 } 66 int main(){ 67 while(~scanf("%d",&n)){ 68 init();; 69 for(int i=1;i<=n;i++){ 70 addE(sb,n*n+n+i,1,0.0); 71 addE(n*n+i,se,1,0.0); 72 } 73 for(int i=1,x;i<=n;i++){ 74 for(int j=1;j<=n;j++){ 75 scanf("%d",&x); 76 addE(n*n+n+j,(i-1)*n+j,1,0.0); 77 addE((i-1)*n+j,n*n+i,1,-log(1.0*x)); 78 } 79 } 80 mfml(); 81 for(int i=1;i<=n;i++) 82 for(int j=head[n*n+n+i];~j;j=S[j].ne){ 83 if(S[j].w||S[j].v==sb) continue; 84 printf("%d%c",(S[j].v-1)/n+1," "[i==n]); 85 break; 86 } 87 } 88 return 0; 89 }
以上是关于Gym - 102346G Getting Confidence 最小费用最大流的主要内容,如果未能解决你的问题,请参考以下文章
Gym101522A Gym101522C Gym101522D
OpenAI Gym 入门与提高 Gym环境构建与最简单的RL agent
强化学习 平台 openAI 的 gym 安装 (Ubuntu环境下如何安装Python的gym模块)
2016 USP-ICMC-Codeforces-Gym101063C-Sleep Buddies Gym101063F-Bandejao Gym101063J-The Keys