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," \n"[i==n]);
85 break;
86 }
87 }
88 return 0;
89 }
