一.CF1209D Cow and Snacks
1.本题考查的是并查集(本人考虑的是匈牙利算法 一--一)
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
匈牙利算法考查的是二分图的最大匹配问题(脑抽了)
本题就是在考查连通块个数
2.思路如下:
第一位客人肯定把他的喜爱口味全会取走,为了让结果更优,接下来的客人的喜爱口味与之有重合,这样他就只会取走一个零食,以此类推……于是建一个n个点m条边的图。第m条边连接ai,bi 两点。显然这样会形成若干个连通块。对于每一个连通块如上述处理,假设该连通块有 x个点,那么该连通块中最终有 x-1位客人可以取走零食。于是答案就变成了统计每个连通块的点数
for(int i=1;i<=n;i++) f[i]=i;
while(k--){
scanf ("%d%d",&x,&y);
int r1=find(x),r2=find(y);
if(r1!=r2) f[r1]=r2;
else ans++;
}
printf("%d\n",ans);
然后就结束了(肥肠煎蛋 PS:非常简单0w0)
3.一定要先分析好考查的是哪种问题(血的教训)
二.P2330 繁忙的都市
1.本题考查最小生成树
2.可以用kruskal算法(并查集),其思想如下:
(1)将边权按照权重从小到大排序
(2)枚举每条边和权重
struct edge{
int a,b,w;
bool operator<(const edge&W) const{
return w<W.w;
}
}e[51000];
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
3.第一问求选择的道路数,因为只有“保证连通”一个条件优先级在“道路尽量少”之上,不难看出直接输出n-1(一个N个点的联通图最少有n-1条边)。第二问直接在求最小生成树的同时,记录下当前已搜到的最大值。由于此题未要求输出最小生成树的权值和,因此在求最小生成树的过程中直接只记录最大值。
void un(int x,int y){
int xx=find(x);
int yy=find(y);
f[xx]=yy;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
e[i]=(edge){u,v,c};
}
for(int i=1;i<=n;i++) f[i]=i;
sort(e+1,e+m+1);
for(int i=1;i<=m;i++){
if(find(f[e[i].a])!=find(f[e[i].b])) {
un(e[i].a,e[i].b);
maxx=e[i].w;
k++;
}
if(k==n-1) break;
}
cout<<n-1<<" "<<maxx;
return 0;
}
The end......