题解 秘密行动
能把题面写得这么难懂也是难为出题人了(
发现质因子之间是独立的
每个位置每种质因子只有选和不选两种可能
发现那个贡献其实就是两个数的某个质因子一个选一个不选有额外贡献
经典问题,最小割即可
然而贡献是乘积需要取对数化为加法
- 实数网络流 \(\tt INF\) 开太大会导致小数位精度很低,最好需要多少开多少
- 实数网络流若出现明明图是连通的但是跑出来流量是 0 的情况试试把 \(\tt INF\) 开小点
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 5010
#define ll long long
//#define int long long
int n, m;
const double eps=1e-8;
int p[N], id[N][N], a[N], b[N], pc[N], tot;
int head[N], cur[N], dep[N], ecnt=1, s, t;
double f[N], c[N][N], d[N][N], sval[N], tval[N], ans;
struct edge{int to, next; double val;}e[N<<1];
inline void add(int s, int t, double w) {e[++ecnt]={t, head[s], w}; head[s]=ecnt;}
bool bfs(int s, int t) {
for (int i=1; i<=tot; ++i) dep[i]=0;
queue<int> q;
dep[s]=1; cur[s]=head[s];
q.push(s);
while (q.size()) {
int u=q.front(); q.pop();
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (e[i].val>eps && !dep[v]) {
dep[v]=dep[u]+1;
cur[v]=head[v];
if (v==t) return 1;
q.push(v);
}
}
}
return 0;
}
double dfs(int u, double in) {
if (u==t||in<eps) return in;
double rest=in, tem;
for (int i=cur[u],v; ~i; cur[u]=i=e[i].next) {
v = e[i].to;
if (e[i].val>eps&&dep[v]==dep[u]+1) {
tem=dfs(v, min(rest, e[i].val));
if (tem<eps) dep[v]=0;
rest-=tem;
e[i].val-=tem;
e[i^1].val+=tem;
if (rest<eps) break;
}
}
return in-rest;
}
signed main()
{
freopen("secret.in", "r", stdin);
freopen("secret.out", "w", stdout);
ios::sync_with_stdio(0);
cin>>n>>m;
memset(head, -1, sizeof(head));
for (int i=1; i<=10; ++i) cin>>p[i]>>f[i], f[i]=log(f[i]);
for (int i=1; i<=n; ++i) {
for (int j=1; j<=10; ++j) cin>>c[i][j], c[i][j]=log(c[i][j]);
for (int j=1; j<=10; ++j) cin>>d[i][j], d[i][j]=log(d[i][j]);
}
for (int i=1; i<=m; ++i) cin>>a[i]>>b[i]>>pc[i];
for (int i=1; i<=n; ++i) for (int j=1; j<=10; ++j) id[i][j]=++tot;
s=++tot; t=++tot;
for (int i=1; i<=n; ++i) for (int j=1; j<=10; ++j) {
add(s, id[i][j], c[i][j]), add(id[i][j], s, 0);
add(id[i][j], t, d[i][j]), add(t, id[i][j], 0);
}
for (int i=1; i<=m; ++i) {
add(id[a[i]][pc[i]], id[b[i]][pc[i]], f[pc[i]]), add(id[b[i]][pc[i]], id[a[i]][pc[i]], 0);
add(id[b[i]][pc[i]], id[a[i]][pc[i]], f[pc[i]]), add(id[a[i]][pc[i]], id[b[i]][pc[i]], 0);
}
while (bfs(s, t)) ans+=dfs(s, 1e4); //, cout<<1<<endl;
// cout<<"ans: "<<ans<<endl;
printf("%.10lf\n", exp(ans));
return 0;
}