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;
题意:聪聪希望求出一种部落划分的方法,使靠得最近的两个部落尽可能远离
处理技巧:将距离从小到大排序,每次合并一个部落就达到了使靠得最近的两个部落尽可能远离
。
(避免二分,用最小生成树变型)
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 思维+并查集+最短路的主要内容,如果未能解决你的问题,请参考以下文章