【好题】二分图构造+bfs+拆绝对值——UCF 2016 K

/*
首先想到拆绝对值
    ta-tb = ha-hb
    ta+tb = ha+hb
可以发现,两个特征值之差/和 相等的点可以互相跳跃
那么构造出一幅二分图,左边是所有特征值之差,右边是所有特征值之和,每个点(除结点1外)代表了一条边
 要求的结果,显然是从结点1的和|差一直到达结点n的和|差所经过的结点个数
 因为每次在点上转换代表必须跳一下
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define N 1000005

int d[N],n,h[N],t[N],id,id1,id2,s1,s2;
map<ll,int> mpl,mpr;
vector<int>G[N];
 
int main(){
    int T;cin>>T;
    for(int tt=1;tt<=T;tt++){
        mpl.clear();mpr.clear();id=0;
        memset(d,0,sizeof d);
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d",&t[i]);
        for(int i=1;i<=n;i++)scanf("%d",&h[i]);
        for(int i=1;i<=n;i++){
            ll sum=(ll)t[i]+h[i];
            if(mpl.count(sum)==0)mpl[sum]=++id; 
            ll dif=(ll)t[i]-h[i];
            if(mpr.count(dif)==0)mpr[dif]=++id;
        }
        for(int i=2;i<n;i++){//连边 
            ll sum=(ll)t[i]+h[i];
            ll dif=(ll)t[i]-h[i];
            int u=mpl[sum],v=mpr[dif];
            G[u].push_back(v);
            G[v].push_back(u);     
        } 
         
        s1=mpl[t[1]+h[1]];
        s2=mpr[t[1]-h[1]];//两个起点 
        id1=mpl[t[n]+h[n]];
        id2=mpr[t[n]-h[n]];//两个终点 
        
        queue<int>q;while(q.size())q.pop();
        q.push(s1);q.push(s2);
        d[s1]=d[s2]=1;
        while(q.size()){
            int u=q.front();q.pop();
            for(auto v:G[u]){
                if(d[v])continue;
                d[v]=d[u]+1;q.push(v);
            }    
        } 
        
        if(!d[id1] && !d[id2]){
            printf("Field #%d: -1

",tt);    
        }else if(!d[id1]){
            printf("Field #%d: %d

",tt,d[id2]);    
        }else if(!d[id2]){
            printf("Field #%d: %d

",tt,d[id1]);    
        }else {
            printf("Field #%d: %d

",tt,min(d[id1],d[id2]));    
        }
        
        for(int i=1;i<=id;i++)G[i].clear();
    }    
} 
原文地址:https://www.cnblogs.com/zsben991126/p/12599984.html