zoukankan      html  css  js  c++  java
  • HDU6808 Go Running(二分图匹配)

    题意:给定n组点,表示在t分钟,x处有人出现。询问最少有多少人

    每个人都可以从任意地点朝任意方向出发,每分钟走一步。

    题解:

    对于这道题,初始可能有一个想法,将这点放在坐标轴上,有两种直线可以选取,一种是斜率为-1的,一种是斜率为1的

    我们要用这两种直线来覆盖所有的点,问的是直线个数的最小值。如果光这个思考,难度还是比较大的,图论问题最难的就是建模。

    我们再抽象一下,因为方向任意,所以任意一个点都可以从x-t或者x+t,这两个位置转移过来,对于每个点都如此,显然我们可以把他看作是两个集合

    一个集合表示向左走,一个集合表示向右走,因此我们可以把点看作边,而左右位置看作点,只要这个边的任意一个端点被选取即可

    这样就转化成了二分图最小点覆盖问题,等价于二分图最大匹配,在连边的时候,注意去重,因为二分图最大匹配当中两个点之间只能有一条边,但是重边不影响答案。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pll;
    const int N=5e5+10;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    int n,S,T;
    int h[N],ne[N],e[N],f[N],idx;
    map<ll,int> m1[2];
    set<pll> s;
    int d[N],cur[N];
    void init(){
        int i;
        for(i=0;i<=2*n+1;i++){
            h[i]=-1;
        }
        idx=0;
        m1[0].clear();
        m1[1].clear();
        s.clear();
    }
    void add(int a,int b,int c){
        e[idx]=b,ne[idx]=h[a],f[idx]=c,h[a]=idx++;
        e[idx]=a,ne[idx]=h[b],f[idx]=0,h[b]=idx++;
    }
    int bfs(){
        memset(d,-1,sizeof d);
        d[S]=0;
        cur[S]=h[S];
        queue<int> q;
        q.push(S);
        while(q.size()){
            int t=q.front();
            q.pop();
            for(int i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(d[j]==-1&&f[i]){
                    cur[j]=h[j];
                    d[j]=d[t]+1;
                    if(j==T)
                    return true;
                    q.push(j);
                }
            }
        }
        return false;
    }
    int find(int u,int limit){
        if(u==T){
            return limit;
        }
        int i;
        int flow=0;
        for(i=cur[u];i!=-1&&flow<limit;i=ne[i]){
            cur[u]=i;
            int j=e[i];
            if(d[j]==d[u]+1&&f[i]){
                int t=find(j,min(f[i],limit-flow));
                if(!t)
                d[j]=-1;
                else{
                    f[i]-=t;
                    f[i^1]+=t;
                    flow+=t;
                }
            }
        }
        return flow;
    }
    int dinic(){
        int flow;
        int r=0;
        while(bfs()){
            while(flow=find(S,inf))
                r+=flow;
        }
        return r;
    }
    void solve(){
        cin>>n;
        init();
        int cnt1=0,cnt2=0;
        int i;
        S=0,T=2*n+1;
        for(i=1;i<=n;i++){
            ll xi,ti;
            cin>>ti>>xi;
            ll tmp1=xi-ti,tmp2=xi+ti;
            if(!m1[0].count(tmp1)) m1[0][tmp1]=++cnt1;
            if(!m1[1].count(tmp2)) m1[1][tmp2]=++cnt2;
            int id1=m1[0][tmp1];
            int id2=m1[1][tmp2];
            if(s.find({id1,id2})==s.end()){
                s.insert({id1,id2});
                add(id1,n+id2,1);
            }
        }
        for(i=1;i<=cnt1;i++){
            add(S,i,1);
        }
        for(i=1;i<=cnt2;i++){
            add(n+i,T,1);
        }
        cout<<dinic()<<endl;
    }
    int main(){
        ios::sync_with_stdio(false);
        int t;
        cin>>t;
        while(t--){
            solve();
        }
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    PointToPointNetDevice doesn't support TapBridgeHelper
    NS3系列—10———NS3 NodeContainer
    NS3系列—9———NS3 IP首部校验和
    NS3系列—8———NS3编译运行
    【习题 7-6 UVA
    【Good Bye 2017 C】 New Year and Curling
    【Good Bye 2017 B】 New Year and Buggy Bot
    【Good Bye 2017 A】New Year and Counting Cards
    【Educational Codeforces Round 35 D】Inversion Counting
    【Educational Codeforces Round 35 C】Two Cakes
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13585469.html
Copyright © 2011-2022 走看看