您的位置:首页 > 其它

【AtCoder Regular Contest 092】C.2D Plane 2N Points(匈牙利算法/tuple+set 贪心)

2018-03-17 22:20 501 查看
原题链接

题意:给两个长度为n的序列的坐标,分别为(Ai,Bi),(Ci,Di),求最多有多少对坐标满足
Ai<Ci并且Bi<Di。


分析:将满足题中条件的坐标对的下标(i,j)存入vector,然后就是匈牙利模板

复杂度:O(n*m) n RT,m为构成的坐标对的数量

模板解释:http://blog.csdn.net/dark_scope/article/details/8880547

可参见:http://blog.csdn.net/feng_zhiyu/article/details/79309746

匈牙利算法

代码:

#include <bits/stdc++.h>
using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define pb push_back
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int MOD=1e3;
const int N=1e2+5;
const ll maxn=2e5+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};

int n,m;
int a
,b
,c
,d
;
int match
;
bool vis
;
vector<int> g
;
bool dfs(int u)
{
for(auto v:g[u])
{
if(vis[v])
continue;
vis[v]=1;
if(match[v]==-1||dfs(match[v]))
{
match[v]=u;
return true;
}
}
return false;
}
void init()
{
rep(i,0,n+1) g[i].clear();
}
void solve()
{
int ans=0;
mem(match,-1);
rep(i,1,n+1)
{
mem(vis,0);
if(dfs(i))
ans++;
}
cout<<ans<<endl;
}
int main()
{
IO;
cin>>n;
init();
rep(i,1,n+1) cin>>a[i]>>b[i];
rep(i,1,n+1) cin>>c[i]>>d[i];
rep(i,1,n+1)
{
rep(j,1,n+1)
{
if(a[i]<=c[j]&&b[i]<=d[j])
g[i].pb(j);
}
}
solve();
return 0;
}


好用的C++ tuple 操作解决了为啥写一个普通的贪心不能得到AC的答案。

学习了。

tuple用法:http://blog.csdn.net/feng_zhiyu/article/details/79597824

贪心

tuple实际上相当于结构体。

【结构体实现】

#include <bits/stdc++.h>
using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)

struct Node
{
int a,b,flag;
bool operator < (const Node& m)const
{
if(a!=m.a) return a<m.a;
else if(b!=m.b) return b<m.b;
else return flag<m.flag;
}
}a
;
int n;
set<int>st;
4000

void solve()
{
st.clear();
int ans=0;
for(int i=0;i<2*n;i++)
{
int flag=a[i].flag;
if(!flag)
{
st.insert(a[i].b);
}
else
{
auto it=st.lower_bound(a[i].b);
if(it!=st.begin())
{
st.erase(--it);
ans++;
}
}
}
cout<<ans<<endl;
}
int main()
{
while(cin>>n)
{
rep(i,0,n)
{
cin>>a[i].a>>a[i].b;
a[i].flag=0;
}
rep(i,n,2*n)
{
cin>>a[i].a>>a[i].b;
a[i].flag=1;
}
sort(a,a+2*n);
solve();
}
return 0;
}


【tuple实现】

复杂度: O(nlogn)

代码:

#include <bits/stdc++.h>
using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define pb push_back
#define mkp make_pair
#define mkt make_tuple
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int MOD=1e3;
const int N=1e2+5;
const ll maxn=2e5+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
int n;
vector<tuple<int,int,int> >vec;
set<int>st;

void solve()
{
int ans=0;
for(auto v: vec)
{
int x,y,c;
tie(x,y,c)=v;
if(c == 0)
{
st.insert(y);
}
else
{
auto it = st.lower_bound(y);
if(it != st.begin())
{
///cout<<(*it);
st.erase(--it);///每次消除的都是当前位置前的一个坐标对,即set内的点,这样也保证是最优的
ans++;
///cout<<"  ans="<<ans<<endl;
}
}
}
cout<<ans<<endl;
}
void init()
{
vec.clear();
st.clear();
}
int main()
{
//fre;
IO;
while(cin>>n)
{
init();
rep(i,0,n)
{
int a,b;
cin>>a>>b;
vec.pb(mkt(a,b,0));
}
rep(i,0,n)
{
int c,d;
cin>>c>>d;
vec.pb(mkt(c,d,1));
}
sort(vec.begin(),vec.end());
/*for(int i=0; i<vec.size(); i++)
{
int x,y,c;
tie(x,y,c)=vec[i];
cout<<x<<" "<<y<<" "<<c<<endl;
}*/
solve();
}
return 0;
}
/**
3
2 0
3 1
1 3
4 2
0 4
5 5

3
0 0
1 1
5 2
2 3
3 4
4 5

2
2 2
3 3
0 0
1 1

5
0 0
7 3
2 2
4 8
1 6
8 5
6 9
5 4
9 1
3 7

5
0 0
1 1
5 5
6 6
7 7
2 2
3 3
4 4
8 8
9 9
**/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息