标签:tchar ctime task deb ble solution priority fprintf problem
最大的一边直接放到一起贪心即可
着重讲小的一边
已知对于二分图匹配,其答案即为最大流
令时间集合为 \(T = {1,2,3,\dots,maxt}\)
对于每一门课程,按照如下方式建图:
考虑第一门课程:
我们选择一些时间节点分给它,设为 \(T_1\)
假设最大流中任务集合为 \(A\),对应的时间集合为 \(B\),并且 \(|A| =|B|=二分图匹配数量\)
那么根据最大流-最小割定理,相当于在图中割去 \(|A|\) 条边,满足下述性质:
考虑第二门课程:
分给它的时间节点为 \(T_2=\complement _T ^{T_1}\)
这时候假设最大流中任务集合为 \(C\),对应的时间集合为 \(D\),并且 \(|C|=|D|=二分图匹配数量\)
同样拥有上述性质
下面建立新的一张图:
将上述两张图并起来,把左边的汇点和右边的源点去掉,每个左边的时间节点向右边对应的时间节点连边权为 \(1\) 的一条边
下面证明,新图中的每一个割和原来两个图中某两个割的并等价。
所以新图的最小割即为答案
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)
ll read(){
ll x=0,f=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn = 44000;
int n, m;
pii p[maxn], tp[maxn];
struct lzt {
int fi, se, ii;
bool operator < (const lzt &b) const {
if (fi != b.fi) return fi < b.fi;
if (se != b.se) return se < b.se;
return ii < b.ii;
}
};
lzt a[maxn], b[maxn];
priority_queue<int, vector<int>, greater<int> > pq;
namespace task1 {
const int mxst = 1100000;
int f[22][mxst];
void main() {
int mx = (1 << n) - 1, mxt = 0;
rep(i, 1, n) mxt = max(mxt, p[i].se);
rep(i, 1, m) a[i].fi = p[i].fi, a[i].se = p[i].se, a[i].ii = i;
rep(i, m + 1, n) b[i - m].fi = p[i].fi, b[i - m].se = p[i].se, b[i - m].ii = i;
m = n - m; n = n - m;
sort(a + 1, a + n + 1); sort(b + 1, b + m + 1);
rep(i, 0, mxt) rep(j, 0, mx) f[i][j] = 1e9;
f[0][0] = 0;
rep(i, 0, mxt - 1) {
rep(j, 0, mx) {
if (f[i][j] == 1e9) continue;
// 选择第一门
int ind = 0;
rep(k, 1, n) {
if (a[k].fi > i + 1) break;
if (a[k].se < i + 1 || (j & (1 << (k - 1)))) continue;
if (!ind || a[k].se < a[ind].se || (a[k].se == a[ind].se && a[k].ii < a[ind].ii)) ind = k;
}
int nwst = j, ad = 0;
if (ind) nwst += (1 << (ind - 1)), ad = 1;
f[i + 1][nwst] = min(f[i + 1][nwst], f[i][j] + ad);
//选择第二门
int ind2 = 0;
rep(k, 1, m) {
if (b[k].fi > i + 1) break;
if (b[k].se < i + 1 || (j & (1 << (n + k - 1)))) continue;
if (!ind2 || b[k].se < b[ind2].se || (b[k].se == b[ind2].se && b[k].ii < b[ind2].ii)) ind2 = k;
}
int nwst2 = j; ad = 0;
if (ind2) nwst2 += (1 << (n + ind2 - 1)), ad = 1;
f[i + 1][nwst2] = min(f[i + 1][nwst2], f[i][j] + ad);
}
}
int ans = 1e9;
rep(i, 0, mx) ans = min(ans, f[mxt][i]);
printf("%d\n", ans);
}
}
namespace task2 {
struct Dinic{
struct Edge{
int fr,to,cap,flow;
};
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int cur[maxn],d[maxn];
void addedge(int u,int v,int cap){
edges.pb((Edge){u,v,cap,0});
edges.pb((Edge){v,u,0,0});
m=edges.size();
G[u].pb(m-2);G[v].pb(m-1);
}
bool BFS(){
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
vis[s]=1;
d[s]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++){
Edge &e=edges[G[u][i]];
if(!vis[e.to] && e.cap>e.flow){
vis[e.to]=1;
d[e.to]=d[u]+1;
q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a){
if(x==t || !a) return a;
int f,flow=0;
for(int &i=cur[x];i<G[x].size();i++){
Edge &e=edges[G[x][i]];
if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){
e.flow+=f;
a-=f;flow+=f;
edges[G[x][i]^1].flow-=f;
if(!a) break;
}
}
return flow;
}
int MaxFlow(int s,int t){
this->s=s;this->t=t;
int ret=0;
while(BFS()){
memset(cur,0,sizeof(cur));
ret+=DFS(s,1e9);
}
return ret;
}
} gr;
void main() {
int mxt = 0;
rep(i, 1, n) mxt = max(mxt, p[i].se);
rep(i, 1, m) a[i].fi = p[i].fi, a[i].se = p[i].se, a[i].ii = i;
rep(i, m + 1, n) b[i - m].fi = p[i].fi, b[i - m].se = p[i].se, b[i - m].ii = i;
m = n - m; n = n - m;
int s = n + m + mxt + mxt + 1, t = s + 1;
sort(a + 1, a + n + 1); sort(b + 1, b + m + 1);
rep(i, 1, n) gr.addedge(s, i, 1);
rep(i, 1, m) gr.addedge(i + n, t, 1);
rep(i, 1, mxt) gr.addedge(i + n + m, i + n + m + mxt, 1);
rep(i, 1, mxt) {
rep(j, 1, n) if (a[j].fi <= i && a[j].se >= i) gr.addedge(j, i + n + m, 1e9);
rep(j, 1, m) if (b[j].fi <= i && b[j].se >= i) gr.addedge(i + n + m + mxt, j + n, 1e9);
}
printf("%d\n", gr.MaxFlow(s, t));
}
}
void work(){
n = read(), m = read();
rep(i, 1, n) p[i].fi = read(), p[i].se = read();
rep(i, 1, n) tp[i] = p[i];
sort(tp + 1, tp + n + 1);
int nw = 1, ans = 0;
rep(i, 1, 400) {
while (tp[nw].fi <= i && nw <= n) pq.push(tp[nw].se), nw++;
while (!pq.empty() && pq.top() < i) pq.pop();
if (!pq.empty()) ans++, pq.pop();
}
printf("%d\n", ans);
task2::main();
}
int main(){
#ifdef LZT
freopen("in","r",stdin);
#endif
work();
#ifdef LZT
Debug("My Time: %.3lfms", (double)clock() / CLOCKS_PER_SEC);
#endif
}
标签:tchar ctime task deb ble solution priority fprintf problem
原文地址:https://www.cnblogs.com/wawawa8/p/10206686.html