Gym - 101492I 区间限制费用流
https://cn.vjudge.net/problem/Gym-101492I
如果用单个点代表每个区间 利用拆点来限制区间的流量的话 点是 n^2/2+m个 边是2*n^2条
但是这样会T
解法1:单纯形
单纯形套板可以过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> #define N using namespace std; typedef unsigned ui; typedef long double dbl; const dbl eps = 1e-8; ui n, m, c[5001]; dbl a[4001][201], x[201], z; int dcmp(dbl d) { return d < -eps ? -1 : d <= eps ? 0 : 1; } // u in, v out void pivot(ui u, ui v) { swap(c[n + u], c[v]); // row u *= 1 / a[u][v] dbl k = a[u][v]; a[u][v] = 1; for (ui j = 0; j <= n; ++j) a[u][j] /= k; for (ui i = 0; i <= m; ++i) { if (i == u || !dcmp(a[i][v])) continue; k = a[i][v]; a[i][v] = 0; for (ui j = 0; j <= n; ++j) a[i][j] -= a[u][j] * k; } } bool init() { for (ui i = 1; i <= n; ++i) c[i] = i; while (1) { ui u = 0, v = 0; for (ui i = 1; i <= m; ++i) if (dcmp(a[i][0]) == -1 && (!u || dcmp(a[u][0] - a[i][0]) == 1)) u = i; if (!u) return 1; for (ui j = 1; j <= n && !v; ++j) if (dcmp(a[u][j]) == -1) v = j; if (!v) return 0; pivot(u, v); } } int simplex() { if (!init()) return 0; else while (1) { ui u = 0, v = 0; for (ui j = 1; j <= n; ++j) if (dcmp(a[0][j]) == 1 && (!v || a[0][j] > a[0][v])) v = j; if (!v) { z = -a[0][0]; for (ui i = 1; i <= m; ++i) x[c[n + i]] = a[i][0]; return 1; } dbl w = 1e20; for (ui i = 1; i <= m; ++i) if (dcmp(a[i][v]) == 1 && dcmp(w - a[i][0] / a[i][v]) == 1) { w = a[i][0] / a[i][v]; u = i; } if (!u) return 2; pivot(u, v); } } int main(void) { ios::sync_with_stdio(0); cin.tie(0); #ifndef ONLINE_JUDGE ifstream cin("1.in"); #endif ui t; cin >> n >> m; for (ui j = 1; j <= n; ++j) cin >> a[0][j]; for (ui i = 1; i <= m; ++i) { int l, r; cin >> l >> r; for (int j = l; j <= r; ++j) a[i][j] = 1; cin >> a[i][0]; } int res = simplex(); if (res == 0) cout << "Infeasible" << endl; else if (res == 2) cout << "Unbounded" << endl; else { cout << (long long)z << endl; } return 0; }
解法2:网络流
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #include<stack> #include<vector> #include<string.h> #include<string> #include<stdlib.h> #define inf 0x3f3f3f3f typedef long long ll; using namespace std; const int maxn=300; const int maxm=10005; struct node { int t,f,c,next; }e[maxm*2]; int a[maxn]; int head[maxn],dis[maxn],vis[maxn]; int pre[maxn]; int cnt,s,t; void add(int s,int t,int c,int f) { e[cnt].t=t; e[cnt].c=c; e[cnt].f=f; e[cnt].next=head[s]; head[s]=cnt++; e[cnt].t=s; e[cnt].c=0; e[cnt].f=-f; e[cnt].next=head[t]; head[t]=cnt++; } void intt() { cnt=0; s=0;t=250; memset(head,-1,sizeof(head)); } int spfa() { queue<int >que; for(int i=0;i<maxn;i++) { dis[i]=inf; vis[i]=0; pre[i]=-1; } dis[s]=0; vis[s]=1; que.push(s); while(que.size()) { int u=que.front(); que.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].t; if(e[i].c>0&&dis[u]+e[i].f<dis[v]) { dis[v]=dis[u]+e[i].f; pre[v]=i; if(vis[v]==0) { vis[v]=1; que.push(v); } } } } if(pre[t]==-1)return 0; return 1; } ll mincost() { int flow=0; ll cost=0; while(spfa()) { int tf=inf; for(int i=pre[t];i!=-1;i=pre[e[i^1].t]) tf=min(e[i].c,tf); flow+=tf; for(int i=pre[t];i!=-1;i=pre[e[i^1].t]) { e[i].c-=tf; e[i^1].c+=tf; cost+=1ll*e[i].f*tf; } } return cost; } int main() { int n,m; scanf("%d%d",&n,&m); memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); intt(); for(int i=1;i<=m;i++) { int u,v,k; scanf("%d%d%d",&u,&v,&k); add(u,v+1,inf,k); } for(int i=n+1;i>=2;i--) add(i,i-1,inf,0); for(int i=n+1;i>=1;i--) { int temp=a[i]-a[i-1]; if(temp<0) { add(i,t,-temp,0); } else add(s,i,temp,0); } printf("%lld\n",mincost()); }
转载自https://blog.csdn.net/dhydye/article/details/80515359 不懂原理QAQ