心好累拿了3天二十分了,其实今天的题还好主要是状态不是太好,这几天被烦心事烦得不行,淡啦。
T1tree
题目其实就是给你一棵唯一的最小生成树,然后让你求出最小的所有边权和。想到最小生成树这些东西首先往并查集那方面想,首先将所有边从小到大排序,然后对于每一条边,它对答案的贡献应该为size[a]size[b] (len[e]+1)-1 所以这个题就转化为一道并查集的应用题,代码很短很容易。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
struct edge{
int u,v,w;
}e[20010];
int n,m,d,t,g,fat[20010],siz[20010];
long long int ans;
int father(int x){if (fat[x]==x)return x;fat[x]=father(fat[x]);return fat[x];}
int unionn(int a,int b){int fa=father(a),fb=father(b);fat[fa]=fb;siz[fb]+=siz[fa];}
int cmp(const edge &x,const edge &y){return x.w<y.w;}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
cin>>t;
while(t--)
{
ans=0;
memset(siz,0,sizeof(siz));
cin>>n;
for (int i=1;i<=n;i++)
{
fat[i]=i;
siz[i]=1;
}
for (int i=1;i<n;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+1,e+n,cmp);
for (int i=1;i<n;i++)
{
ans+=1ll*siz[father(e[i].u)]*siz[father(e[i].v)]*(e[i].w+1)-1;
unionn(e[i].u,e[i].v);
}
cout<<ans<<endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}
t2是一道计算几何题
• n2 把每条直线搞出来,记下它的端点、长度、中点。然后按
中点排序。中点相同的按距离排序。在两者都相同的情况下
用平⽅级别的算法暴⼒更新答案。
• 似乎会 T,但是由于端点坐标都是整数,然后以某个点为圆
⼼,半径为正整数的圆经过的整数点其实不会太多,所以就
放⼼写吧 ∼
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
#define cmax(x) (ans<x?ans=x:1)
#define abs(x) (x<0?-(x):x)
const int MAXBUF=1<<22;
char B[MAXBUF],*T=B,*S=B;
typedef long long int ll;
#define getc() (S==T&&(T=(S=B)+fread(B,1,MAXBUF,stdin),S==T)?EOF:*S++)//读入优化
inline ll F(){register ll aa;register int bb,ch;
while (ch=getc(),(ch>'9'||ch<'0')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
while (ch=getc(),ch>='0'&&ch<='9')aa=aa*10+ch-'0';return bb?aa:-aa;}
struct P{//存点
ll x,y;
}a[1510];
P operator+(const P &a,const P &b){return (P){a.x+b.x,a.y+b.y};}
P operator-(const P &a,const P &b){return (P){a.x-b.x,a.y-b.y};}
bool operator<(const P &a,const P &b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
struct L{
P p;int x,y;ll d;//存边
}l[1125010];
bool operator<(const L &x,const L &y){return x.d<y.d||(x.d==y.d&&x.p<y.p);}
int n,tot;ll ans;
ll l2(const P &a){return a.x*a.x+a.y*a.y;}//计算距离
ll cross (const P &a,const P &b){return abs(a.x*b.y-a.y*b.x);} //叉积
#define calc(a,b,c) (cross(b-a,c-a))//计算叉积
void getans(int x,int y)
{
for (int i=x;i<=y;i++)
for (int j=x;j<i;j++)
cmax(calc(a[l[i].x],a[l[j].x],a[l[j].y]));
}
int main()
{
freopen("rectangle.in","r",stdin);
freopen("rectangle.out","w",stdout);
n=F();//cout<<n;
for (int i=1;i<=n;i++)
a[i]=(P){F(),F()};
sort(a+1,a+1+n);//按照x大小排序
for (int i=1;i<=n;i++)
for (int j=1;j<i;j++)
l[++tot]=(L){a[i]+a[j],j,i,l2(a[i]-a[j])};//关键字依次为中点,端点在数组中的序号,向量的模
sort(l+1,l+tot+1);//按照距离(主要)中点(次要)排序
for (int i=1,j;i<=tot;getans(i,j-1),i=j) //枚举寻找距离、中点都相等的向量,更新答案
for (j=i+1;l[i].d==l[j].d&&l[i].p.x==l[j].p.x&&l[i].p.y==l[j].p.y;j++);
cout<<ans;//cout<<a[1].x<<a[1].y;cout<<n;
fclose(stdin);
fclose(stdout);
return 0;
}
t3又是一道搜索题,而且是我比较擅长的状态压缩的广搜题,其实代码不难写,但!是!忘!了!加!边!界!的!限!定!条!件!了!然后爆了零QAQ,之后改代码改了几分钟就改过来了TAT,附上代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
int ex,ey,sx,sy;
struct node{
int sit,x,y,ti;
}st,en,now,k;
int n,m,had,vis[510][510][4];
string s;
char pic[510][510];
char ch;
queue<node>q;
int main()
{
freopen("cuboid.in","r",stdin);
freopen("cuboid.out","w",stdout);
memset(vis,0,sizeof(vis));
cin>>n>>m;
had=0;
for (int i=1;i<=n;i++)
{
cin>>s;
for (int j=1;j<=m;j++)
{
pic[i][j]=s[j-1];
if (pic[i][j]=='O'){ex=i;ey=j;}
if (pic[i][j]=='X'){sx=i;sy=j;}
}
}
st.x=sx;st.y=sy;st.sit=1;st.ti=0;
if (pic[sx-1][sy]=='X'){st.sit=3;st.x=sx-1;st.y=sy;}
else if (pic[sx][sy-1]=='X'){st.sit=2;st.x=sx;st.y=sy-1;}
q.push(st);
vis[st.x][st.y][st.sit]=1;
while(!q.empty())
{
now=q.front();
int x=now.x,y=now.y;
q.pop();
now.ti++;
if (now.sit==1)
{
if (x>2)if (!vis[x-2][y][3]&&pic[x-2][y]!='#'&&pic[x-1][y]!='#')
{vis[x-2][y][3]=1;k=now;k.sit=3;k.x-=2;q.push(k);}
if (y>2)if (!vis[x][y-2][2]&&pic[x][y-2]!='#'&&pic[x][y-1]!='#')
{vis[x][y-2][2]=1;k=now;k.sit=2;k.y-=2;q.push(k);}
if (x<n-1&&!vis[x+1][y][3]&&pic[x+1][y]!='#'&&pic[x+2][y]!='#')
{vis[x+1][y][3]=1;k=now;k.sit=3;k.x++;q.push(k);}
if (y<m-1&&!vis[x][y+1][2]&&pic[x][y+2]!='#'&&pic[x][y+1]!='#')
{vis[x][y+1][2]=1;k=now;k.sit=2;k.y++;q.push(k);}
}
if (now.sit==2)
{
if (ex==x&&(ey==y+2||ey==y-1))
{cout<<now.ti;had=1;break;}
if (x>1&&!vis[x-1][y][2]&&pic[x-1][y]!='#'&&pic[x-1][y+1]!='#')
{vis[x-1][y][2]=1;k=now;k.x--;q.push(k);}
if (x<n&&y<m&&!vis[x+1][y][2]&&pic[x+1][y]!='#'&&pic[x+1][y+1]!='#')
{vis[x+1][y][2]=1;k=now;k.x++;q.push(k);}
if (y>1&&!vis[x][y-1][1]&&pic[x][y-1]=='.')
{vis[x][y-1][1]=1;k=now;k.sit=1;k.y--;q.push(k);}
if (y<m-1&&!vis[x][y+2][1]&&pic[x][y+2]=='.')
{vis[x][y+2][1]=1;k=now;k.sit=1;k.y+=2;q.push(k);}
}
if (now.sit==3)
{
if(ey==y&&(ex==x-1||ex==x+2))
{cout<<now.ti;had=1;break;}
if (y>1&&!vis[x][y-1][3]&&pic[x][y-1]!='#'&&pic[x+1][y-1]!='#')
{vis[x][y-1][3]=1;k=now;k.y--;q.push(k);}
if (y<m&&!vis[x][y+1][3]&&pic[x][y+1]!='#'&&pic[x+1][y+1]!='#')
{vis[x][y+1][3]=1;k=now;k.y++;q.push(k);}
if (x>1&&!vis[x-1][y][1]&&pic[x-1][y]=='.')
{vis[x-1][y][1]=1;k=now;k.sit=1;k.x--;q.push(k);}
if (x<n-1&&!vis[x+2][y][1]&&pic[x+2][y]=='.')
{vis[x+2][y][1]=1;k=now;k.sit=1;k.x+=2;q.push(k);}
}
}
if (!had)cout<<"Impossible";
fclose(stdin);
fclose(stdout);
return 0;
}