棋盘V 最小费用最大流

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。

来源/分类

中山纪念中学20170301 

解题思路:题目应该是让尽可能猜错,并且猜的所有边不能相同。

因为要尽可能猜错,我们就把错误的点连边容量为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);
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/83063290