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;
}