12.25:最小生成树
题目链接:22NYIST最小生成树专题 [Cloned] - Virtual Judge (vjudge.net)
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
int f[10005];
struct node
{
int a, b;
int w;
}p[10005];
bool cmp(node x , node y)
{
return x.w < y.w;
}
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
int main(){
int y;
while(~scanf("%d",&y)){
if(y==0) break;
int n;
int sum=0;
n=y*(y-1)/2;
int cnt=0;
while(n--){
scanf("%d %d %d",&p[cnt].a,&p[cnt].b,&p[cnt].w);
cnt++;
}
sort(p,p+cnt,cmp);
for(int i=1;i<=y;i++)f[i]=i;
for(int i=0;i<cnt;i++){
int a = p[i].a , b =p[i].b , w = p[i].w;
a = find(a);
b = find(b);
if(a==b) continue;
else{
f[a]=b;
sum+=w;
}
}
cout<<sum<<endl;;
}
}
12.26
现在基本上熟悉板子题了
题目链接:22NYIST最小生成树专题 [Cloned] - Virtual Judge (vjudge.net)
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
int f[10005];
struct node{
int a,b;
double d;
}p[10005];
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
int cmp(node x,node y){
return x.d<y.d;
}
double x[105],y[105];
int main(){
int n;
int t;
cin>>t;
while(t--){
cin>>n;
int cnt=0;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=n;i++) cin>>x[i]>>y[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) continue;
p[cnt].a=i;p[cnt].b=j;
p[cnt].d=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
if(p[cnt].d>1000||p[cnt].d<10) cnt--;
cnt++;
}
}
sort(p,p+cnt,cmp);
double sum=0;
for(int i=0;i<cnt;i++){
int a=find(p[i].a),b=find(p[i].b);
if(a==b) continue;
else {
f[a]=b;
sum+=p[i].d;
}
}
int p=0;
for(int i=1;i<n;i++){
if(find(i)!=find(i+1))p++;
}
if(p!=0) cout<<"oh!"<<endl;
else printf("%.1f\n",sum*100);
}
}
12.27
周赛的折线分割面
题目链接:NYIST集训队 12.24周赛 - Virtual Judge (vjudge.net)
整体思路:先推导一根线的公式,然后一个折线就相当于两根直线只不过三个面变成一个面,然后推导出公式:f(n) = ((1 + n) * n / 2) + 1 - 2 * n = 2 * n * n - n + 1。
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
typedef long long ll;
using namespace std;
int main(){
int t,n;
cin>>t;
while(t--){
cin>>n;
cout<<2*n*n-n+1<<endl;
}
}
12.28
周赛b题
题目链接:NYIST集训队 12.24周赛 - Virtual Judge (vjudge.net)
整体思路:就是找到先标记然后,先到两个标记的就是可以保存的,然后其他就要删除。
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
typedef long long ll;
using namespace std;
int t[105];
int main(){
ll t1;
cin>>t1;
while(t1--){
ll len,sum=0;
memset(t,0,sizeof(t));
string a;
cin>>a;
len=a.length();
for(int i=0;i<len;i++){
if(t[a[i]-'a']==1){
memset(t,0,sizeof(t));
sum+=2;
}
else {
t[a[i]-'a']=1;
}
}
cout<<len-sum<<endl;
}
}