6445: 棋盘V
时间限制: 1 Sec 内存限制: 128 MB
提交: 402 解决: 50
[提交] [状态] [讨论版] [命题人:admin]
题目描述
有一块棋盘,棋盘的边长为100000,行和列的编号为1到100000。棋盘上有n个特殊格子,任意两个格子的位置都不相同。
现在小K要猜哪些格子是特殊格子。她知道所有格子的横坐标和纵坐标,但并不知道对应关系。换言之,她只有两个数组,一个存下了所有格子的横坐标,另一个存下了所有格子的纵坐标,而且两个数组都打乱了顺序。当然,小K猜的n个格子的位置也必须都不相同。
请求出一个最大的k,使得无论小K怎么猜,都能猜对至少k个格子的位置。
输入
输入数据第一行包含一个整数n。
接下来n行,每行描述一个特殊格子的位置。第i行含有两个整数xi和yi ,代表第i个格子的坐标。保证任意两个格子的坐标都不相同。
输出
输出一行,包含一个整数,代表最大的k。
样例输入
2 1 1 2 2
样例输出
0
提示
小K有可能会猜(1,2),(2,1),此时一个都没对
对于30%的数据,n≤8。
另外有5%的数据,所有横坐标和纵坐标均不相同。
另外有15%的数据,所有横坐标或者纵坐标均不相同。
对于100%的数据,n≤50,1≤xi,yi≤100000。
来源/分类
解题思路:题目应该是让尽可能猜错,并且猜的所有边不能相同。
因为要尽可能猜错,我们就把错误的点连边容量为1 费用为0
正确的边容量为1 费用为1
对于原点和汇点,于每个点连边,容量为该点出现的次数 费用为0
这样去跑最小费用最大流的话就会优先跑费用为0的边。。。
关于这一题,我真的是交的心态崩了。。。。
我用flase表示当前点不在队列里,一不小心把出队写成了true。。。
然后就没有然后了。。。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 505
#define inf 0x3f3f3f3f
int mp[305][305];
int visx[1005],visy[1005];
int visxy[305][305];
int a[1005],b[1005];
struct edg
{
int u,to,flow,cost,nt;
}g[100005];
int tot=0;
int head[100005];
void addedg(int u,int v,int flow,int cost)
{
g[tot].to=v;
g[tot].flow=flow;
g[tot].cost=cost;
g[tot].nt=head[u];
head[u]=tot++;
g[tot].to=u;
g[tot].flow=0;
g[tot].cost=-1*cost;
g[tot].nt=head[v];
head[v]=tot++;
}
int S,T;
void creat(int n)
{
sort(b+1,b+1+2*n);
int cnt=unique(b+1,b+1+2*n)-b-1;
memset(mp,0,sizeof(mp));
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
memset(visxy,0,sizeof(visxy));
memset(head,-1,sizeof(head));
rep(i,1,n)
{
a[i]=lower_bound(b+1,b+1+cnt,a[i])-b;
a[n+i]=lower_bound(b+1,b+1+cnt,a[n+i])-b;
visx[a[i]]++;
visy[a[n+i]]++;
mp[a[i]][a[n+i]]=1;
}
rep(i,1,n)
{
rep(j,n+1,2*n)
{
//cout<<"ce "<<a[i]<<" "<<a[j]<<endl;
if(visxy[a[i]][a[j]])continue;
if(mp[a[i]][a[j]])
{
//cout<<a[i]<<" "<<a[j]<<" 1"<<endl;
addedg(a[i],a[j]+cnt,1,1);
}
else
{
//cout<<a[i]<<" "<<a[j]<<" 0"<<endl;
addedg(a[i],a[j]+cnt,1,0);
}
visxy[a[i]][a[j]]=1;
}
}
S=0;
T=cnt+cnt+1;
for(int i=1;i<=cnt;i++)
{
if(visx[i])
{
addedg(S,i,visx[i],0);
}
if(visy[i])
{
addedg(i+cnt,T,visy[i],0);
}
}
}
int vis[100005],dist[100005];
struct node
{
int id,v;
}pre[100005];
bool spfa(int s,int t)
{
memset(vis,false,sizeof(vis));
memset(dist,inf,sizeof(dist));
queue<int>q;
vis[s]=true;
q.push(s);
dist[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=g[i].nt)
{
int to=g[i].to;
if(dist[to]>dist[u]+g[i].cost&&g[i].flow>0)
{
dist[to]=dist[u]+g[i].cost;
pre[to].id=i;
pre[to].v=u;
if(vis[to]==false)
{
vis[to]=true;
q.push(to);
}
}
}
}
return dist[t]==inf?false:true;
}
void solve(int s,int t)
{
int ans=0;
int mini=inf;
while(spfa(s,t))
{
mini=inf;
int cost=0;
for(int i=t;i!=s;i=pre[i].v)
{
mini=min(mini,g[pre[i].id].flow);
}
for(int i=t;i!=s;i=pre[i].v)
{
g[pre[i].id].flow-=mini;
g[pre[i].id^1].flow+=mini;
}
ans+=dist[t]*mini;
}
printf("%d\n",ans);
}
int main()
{
int n;
sca(n);
rep(i,1,n)
{
scanf("%d%d",&a[i],&a[i+n]);
b[i]=a[i],b[n+i]=a[n+i];
}
creat(n);
solve(S,T);
}