标准解是贪心:
题解:
贪心即可。
先将翻晒霜按spf值排序,从小到大处理。
对于当前处理的防晒霜,找到能使用它且spf上界最小的牛,将防晒霜供其使用。
因为上界越大,选择越多,在之后可能也可以找到匹配的防晒霜,
而由于从小到大处理,下界已经没有意义(不可能找到比当前spf更小的匹配),这是贪心的原则。
贪心即可。
先将翻晒霜按spf值排序,从小到大处理。
对于当前处理的防晒霜,找到能使用它且spf上界最小的牛,将防晒霜供其使用。
因为上界越大,选择越多,在之后可能也可以找到匹配的防晒霜,
而由于从小到大处理,下界已经没有意义(不可能找到比当前spf更小的匹配),这是贪心的原则。
注意:
while(k<=c && nodeCow[k].a<=a) //do not add "&& nodeCow[k].b>=a"
{
pq.push(nodeCow[k++].b);
}
否则这个while就可能中断,可以改成:
while(k<=c && nodeCow[k].a<=a) //do not add "&& nodeCow[k].b>=a"
{
if(nodeCow[k].b>=a) //但是会超时,好蛋疼
{
pq.push(nodeCow[k++].b);
}
}
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define C 2505
#define L 2505
struct NODE
{
int a,b;
};
NODE nodeCow[C];
NODE nodeSun[L];
int cmp(NODE x, NODE y)
{
return x.a<y.a;
}
struct lessPQ
{
bool operator()(int a, int b)
{
return a>b;
}
};
int main()
{
int c,l,i,j,k,a,b,sum;
priority_queue<int, vector<int>, lessPQ> pq;
cin>>c>>l;
for(i=1;i<=c;i++)
{
cin>>nodeCow[i].a>>nodeCow[i].b;
}
for(i=1;i<=l;i++)
{
cin>>nodeSun[i].a>>nodeSun[i].b;
}
sort(nodeCow+1,nodeCow+1+c,cmp);
sort(nodeSun+1,nodeSun+1+l,cmp);
/*
for(i=1;i<=c;i++)
{
cout<<nodeCow[i].a<<" "<<nodeCow[i].b<<endl;
}
for(i=1;i<=l;i++)
{
cout<<nodeSun[i].a<<" "<<nodeSun[i].b<<endl;
}
*/
sum=0;
k=1;
for(i=1;i<=l;i++)
{
for(j=1;j<=nodeSun[i].b;j++)
{
a=nodeSun[i].a;
while(k<=c && nodeCow[k].a<=a)
{
pq.push(nodeCow[k++].b);
}
while(!pq.empty())
{
b=pq.top();
pq.pop();
//cout<<b<<endl;
if(b>=a)
{
sum++;
break;
}
}
}
}
cout<<sum<<endl;
return 0;
}
网络流解法:
建图:s到每头牛连边,边权为1
每个防晒霜到t连边,边权为使用次数
每头牛到能使用的防晒霜连边,边权为1
/*
* Dinic algo for max flow
*
* This implementation assumes that #nodes, #edges, and capacity on each edge <= INT_MAX,
* which means INT_MAX is the best approximation of INF on edge capacity.
* The total amount of max flow computed can be up to LLONG_MAX (not defined in this file),
* but each 'dfs' call in 'dinic' can return <= INT_MAX flow value.
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#include <queue>
#include <vector>
# include<iostream>
# include<cstring>
# include<map>
#include<algorithm>
#define C 2505
#define L 2505
#define N (C+L) //==================make sure this is the total node number!
#define M (N*N+4*N)
typedef long long LL;
using namespace std;
struct edge
{
int v, cap, next;
};
edge e[M];
int head[N], level[N], cur[N];
int num_of_edges;
//When there are multiple test sets, you need to re-initialize before each
void dinic_init(void)
{
num_of_edges = 0;
memset(head, -1, sizeof(head));
return;
}
int add_edge(int u, int v, int c1, int c2)
{
int& i=num_of_edges;
assert(c1>=0 && c2>=0 && c1+c2>=0); // check for possibility of overflow
e[i].v = v;
e[i].cap = c1;
e[i].next = head[u];
head[u] = i++;
e[i].v = u;
e[i].cap = c2;
e[i].next = head[v];
head[v] = i++;
return i;
}
void print_graph(int n)
{
for (int u=0; u<n; u++)
{
printf("%d: ", u);
for (int i=head[u]; i>=0; i=e[i].next)
{
printf("%d(%d)", e[i].v, e[i].cap);
}
printf("\n");
}
return;
}
//Find all augmentation paths in the current level graph This is the recursive version
int dfs(int u, int t, int bn)
{
if (u == t) return bn;
int left = bn;
for (int i=head[u]; i>=0; i=e[i].next)
{
int v = e[i].v;
int c = e[i].cap;
if (c > 0 && level[u]+1 == level[v])
{
int flow = dfs(v, t, min(left, c));
if (flow > 0)
{
e[i].cap -= flow;
e[i^1].cap += flow;
cur[u] = v;
left -= flow;
if (!left) break;
}
}
}
if (left > 0) level[u] = 0;
return bn - left;
}
bool bfs(int s, int t)
{
memset(level, 0, sizeof(level));
level[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
if (u == t) return true;
for (int i=head[u]; i>=0; i=e[i].next)
{
int v = e[i].v;
if (!level[v] && e[i].cap > 0)
{
level[v] = level[u]+1;
q.push(v);
}
}
}
return false;
}
LL dinic(int s, int t)
{
LL max_flow = 0;
while (bfs(s, t))
{
memcpy(cur, head, sizeof(head));
max_flow += dfs(s, t, INT_MAX);
}
return max_flow;
}
int upstream(int s, int n)
{
int cnt = 0;
vector<bool> visited(n);
queue<int> q;
visited[s] = true;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i=head[u]; i>=0; i=e[i].next)
{
int v = e[i].v;
if (e[i].cap > 0 && !visited[v])
{
visited[v] = true;
q.push(v);
cnt++;
}
}
}
return cnt; // excluding s
}
struct NODE
{
int a,b;
};
NODE nodeCow[C];
int cmp(NODE x, NODE y)
{
return x.a<y.a;
}
int main()
{
int c,l,a,b,i,j;
dinic_init();
cin>>c>>l;
for(i=1;i<=c;i++)
{
cin>>nodeCow[i].a>>nodeCow[i].b;
add_edge(0,i,1,0);
}
sort(nodeCow+1,nodeCow+1+c,cmp);
for(i=1;i<=l;i++)
{
cin>>a>>b;
add_edge(c+i,c+l+1,b,0);
for(j=1;j<=c;j++)
{
if(nodeCow[j].a<=a)
{
if(nodeCow[j].b>=a)
{
add_edge(j,c+i,1,0);
}
}
else
{
break;
}
}
}
cout<<dinic(0,c+l+1)<<endl;
return 0;
}