3/29 思维+并查集+最短路

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3/29 思维+并查集+最短路相关的知识,希望对你有一定的参考价值。

P3535 [POI2012]TOU-Tour de Byteotia
本题将大于编号k的边相连组成环,若有小于等于k的边进来,并查集判断在环内,则需要累加1删去。

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,k,ans,f[N],head[N];
struct node

    int u,v;
e[N];
bool cmp(node e1,node e2)

    if(e1.u==e2.u) return e1.v>e2.v;
    return e1.u>e2.u;

int r_find(int r)

    if(f[r]==r)
        return f[r];
    f[r]=r_find(f[r]);
    return f[r];

int main()

    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
        cin>>e[i].u>>e[i].v;
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;i++)
    
        if(e[i].u>k&&e[i].v>k)
        
            int fx=r_find(e[i].u),fy=r_find(e[i].v);
            f[fx]=fy;
        
        else
        
            int fx=r_find(e[i].u),fy=r_find(e[i].v);
            if(fx==fy)
            
                ans++;continue;
            
            f[fx]=fy;
        
    
    cout<<ans<<endl;
	return 0;


P4047 [JSOI2010]部落划分

题意:聪聪希望求出一种部落划分的方法,使靠得最近的两个部落尽可能远离
处理技巧:将距离从小到大排序,每次合并一个部落就达到了使靠得最近的两个部落尽可能远离
(避免二分,用最小生成树变型)

n个部落:需要n-1条边变成一个部落
k个部落:k-1条边连接到k个部落
(n-1)-(k-1)条边使得部落变为k个部落==n-k条边组成k个部落
因此两个部落尽可能远离,答案为n-k+1点的距离

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,k,ans,num,f[N],a[N],b[N],cnt;
struct node

    int u,v;double dis;
e[N];
bool cmp(node e1,node e2)

    return e1.dis<e2.dis;

int r_find(int r)

    if(f[r]==r)
        return f[r];
    f[r]=r_find(f[r]);
    return f[r];

int main()

    ios::sync_with_stdio(0); cin.tie(0);
    cout << fixed << setprecision(2);
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i],f[i]=i;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
    
        double dd=sqrt((double)(a[i]-a[j])*(a[i]-a[j])+(double)(b[i]-b[j])*(b[i]-b[j]));
        e[++cnt].u=i,e[cnt].v=j,e[cnt].dis=dd;
    
    sort(e+1,e+cnt+1,cmp);
    int i;
    for(i=1;i<=cnt;i++)
    
        //cout<<e[i].dis<<endl;
        int fx=r_find(e[i].u),fy=r_find(e[i].v);
        if(fx!=fy)
        
            f[fx]=fy;num++;
        
        if(num==n-k+1) break;
    
    cout<<e[i].dis<<endl;
	return 0;


P1073 [NOIP2009 提高组] 最优贸易
vector做法,比链式前向行更方遍,我感觉。照着大佬的思路和码风写了一遍,收获挺多。

#include <bits/stdc++.h>
#define t(x,i) (n*i+x)
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int n,m,dist[N*3],vis[N*3];
vector<pair<int,int> >g[N*3];
void add(int x,int y)

    g[t(x,0)].push_back(t(y,0),0);
    g[t(x,1)].push_back(t(y,1),0);
    g[t(x,2)].push_back(t(y,2),0);

void spfa(int u)

    for(int i=1;i<=n*3;i++) dist[i]=-inf;
    dist[u]=0;
    queue<int>q;q.push(u);
    vis[u]=1;
    while(!q.empty())
    
        int u=q.front();q.pop();vis[u]=0;
        for(auto &k :g[u])
        
            int v=k.first,len=k.second;
            if(dist[v]<dist[u]+len)
            
                dist[v]=dist[u]+len;
                if(!vis[v]) q.push(v),vis[v]=1;
            
        
    

int main()

    ios::sync_with_stdio(0); cin.tie(0);
    cout << fixed << setprecision(2);
    cin>>n>>m;
    for(int i=1,v;i<=n;i++)
    
        cin>>v;
        g[t(i,0)].push_back(t(i,1),-v);
        g[t(i,1)].push_back(t(i,2),v);
    
    for(int i=1,x,y,z;i<=m;i++)
    
        cin>>x>>y>>z;add(x,y);
        if(z==2) add(y,x);
    
    spfa(t(1,0));
    cout<<dist[t(n,2)]<<endl;
	return 0;


CF

CF14B Young Photographer
这个绿题还是蛮简单的,思路一般般,题意得想清楚。我就是刚开始没读明白题意~

#include <bits/stdc++.h>
#define t(x,i) (n*i+x)
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int n,k,num[1005],mi=inf;

int main()

    ios::sync_with_stdio(0); cin.tie(0);
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    
        int x,y;cin>>x>>y;
        if(x>y) swap(x,y);
        for(int g=x;g<=y;g++)
            num[g]++;
    
    int g=mi;
    for(int i=0;i<=1000;i++)
    
        //cout<<num[i]<<endl;
        if(num[i]==n)
            mi=min(mi,abs(i-k));
    
    if(g!=mi)
        cout<<mi<<endl;
    else
        cout<<-1<<endl;
	return 0;


以上是关于3/29 思维+并查集+最短路的主要内容,如果未能解决你的问题,请参考以下文章

HDU2874 Connections between cities(并查集+倍增LCA算法求森林最短路)

bzoj3694: 最短路(树链剖分/并查集)

模板(最短路,最小生成树,并查集)

最短路+并查集

并查集刷题整理

最短路径 kruskal 选边 并查集模板