Outlets
看一眼就应该知道是要求MST。
#include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namespace std; const int N=10000; struct DST { int father[N]; void init() { for (int i=0; i<N; i++) father[i]=i; } int root(int k) { if (father[k]==k) return k; father[k]=root(father[k]); return father[k]; } void merge(int x, int y) { x=root(x),y=root(y); father[x]=father[y]; } }s; struct _point { int x,y; double d; }site[60],edge[N]; inline bool cmp(const _point &a, const _point &b) { return (a.d<b.d); } int main() { int i,j,k,n,p,q,x,y,K; double tot; while (scanf("%d",&n),n) { s.init(); scanf("%d %d",&p, &q); for (i=1; i<=n; i++) { scanf("%d %d",&site[i].x,&site[i].y); } for (i=1,k=0; i<=n; i++) for (j=1; j<=n; j++) if (i!=j) { edge[k].d=sqrt( (site[i].x-site[j].x)*(site[i].x-site[j].x) +(site[i].y-site[j].y)*(site[i].y-site[j].y)+0.0); edge[k].x=i, edge[k].y=j; k++; } K=k; sort(edge,edge+K,cmp); tot=sqrt( (site[p].x-site[q].x)*(site[p].x-site[q].x) +(site[p].y-site[q].y)*(site[p].y-site[q].y)+0.0); s.merge(p,q); for (i=1,k=2; k<n; i++) { x=edge[i].x, y=edge[i].y; x=s.root(x), y=s.root(y); if (x==y) continue; s.merge(x,y); tot+=edge[i].d; k++; } printf("%.2f\n",tot); } return 0; }
Friend Chains
点V=1000,边E=10000,floyd不靠谱,单点最短路径bfs的复杂度是O(V+E),跑V次O(V^2+VE),可以接受,水过。
那个名字用map来hash就好了
#include <stdio.h> #include <string.h> #include <string> #include <map> using namespace std; const int V = 1010; const int E = 25010; int n; int g[V][V],cnt; struct node{ int x,y,w; node *next; }edge[E],*head[V]; inline void addedge(int x, int y, int w){ edge[cnt].x=x, edge[cnt].y=y, edge[cnt].w=w; edge[cnt].next=head[x]; head[x]=edge+cnt++; } void init(){ cnt=0; memset(head,0,sizeof(head)); memset(g,0,sizeof(g)); } int q[V],vis[V],dis[V]; int bfs(int st){ int he,ta,now;//head tail he=1,ta=0; memset(vis,0,sizeof(vis)); memset(dis,7,sizeof(dis)); q[0]=st; vis[st]=true; dis[st]=0; while (ta<he){ now=q[ta++]; //vis[now]=true;//useless for (node* p=head[now]; p; p=p->next){ if (!vis[p->y] && dis[p->y]>dis[now]+p->w) { q[he++]=p->y; vis[p->y]=true; dis[p->y]=dis[now]+p->w; } } } int i,max=0; for (i=0; i<n; i++) if (dis[i]>max) max=dis[i]; return max; } int main() { map<string,int> name; char str[11],s1[11],s2[11]; int m,i,j,k,x,y; while ( scanf("%d",&n),n){ init(); name.clear(); k=0; for (i=0; i<n; i++) { scanf("%s",str); name[str]=i; } scanf("%d",&m); for (i=0; i<m; i++) { scanf("%s %s",s1,s2); x=name[s1], y=name[s2]; g[x][y]=g[y][x]=1; } for (i=0; i<n; i++) for (j=0; j<n; j++) if (g[i][j]) addedge(i,j,1); int tmp; for (i=0,k=0; i<n; i++) { tmp=bfs(i); if (tmp>k) k=tmp; if (k>=n) break; } if (k>=n) k=-1; printf("%d\n",k); } return 0; }
Scaring the Birds
这题二分稻草人的数量,dfs枚举稻草人的组合,然后验证即可。
n似乎不大,直接用循环赋值应该就能A,用线段树求覆盖长度是在干嘛。。。
#include <cstdio> #include<cstring> using namespace std; #define L(u) ( u << 1 ) #define R(u) ( u << 1 | 1 ) #define N 55 struct item{ int l, r; int v, add;}; struct tree{ item node[N*3]; int num[N]; int n, q; void init ( int u, int l, int r ) { node[u].l = l; node[u].r = r; node[u].v = 0; node[u].add = 0; if ( l == r ) return; int mid = ( l + r ) >> 1; init ( L(u), l, mid ); init ( R(u), mid+1, r ); } int set ( int u, int l, int r) { int ret = 0; if ( node[u].v == node[u].r-node[u].l+1 ) return 0; if ( l == node[u].l && node[u].r == r ) { ret = r-l+1-node[u].v; node[u].v = r-l+1; return ret; } int mid = ( node[u].l + node[u].r ) >> 1; if ( r <= mid ) ret = set ( L(u), l, r ); else if ( l > mid ) ret = set ( R(u), l, r ); else { ret = set ( L(u), l, mid ); ret+= set ( R(u), mid+1, r ); } node[u].v += ret; return ret; } int sum ( int u, int l, int r ) { if ( node[u].v == node[u].r-node[u].l+1 ) return r-l+1; if ( l == node[u].l && node[u].r == r ) { return node[u].v; } int mid = ( node[u].l + node[u].r ) >> 1; if ( r <= mid ) return sum ( L(u), l, r ); else if ( l > mid ) return sum ( R(u), l, r ); else return (sum ( L(u), l, mid ) + sum ( R(u), mid+1, r )); } }s[N]; struct Vac{ int x,y,r,vis; }V[N]; bool check(int n, int k, int mid){ int i,j,l,r,p; for (i=1; i<=n; i++) s[i].init(1,1,n); for (i=0; i<k; i++){ s[ V[i].y ].set(1, V[i].x, V[i].x); if (V[i].vis) { for (j=0; j<=V[i].r; j++){ l=V[i].x-(V[i].r-j), r=V[i].x+V[i].r-j; if (l<=0) l=1; if (r>=n) r=n; p=V[i].y-j; if (p>=1) s[p].set(1,l,r); p=V[i].y+j; if (p<=n) s[p].set(1,l,r); } } } for (i=1, j=0; i<=n; i++) j+=s[i].sum(1,1,n); if (j==n*n) return true; else return false; } bool dfs(int n,int k, int d, int mid, int p){ if (d==mid){ return check(n,k,mid); } bool tmp; for (int i=p; i<k; i++){ if (V[i].vis==0){ V[i].vis=1; tmp=dfs(n,k,d+1,mid,i+1); V[i].vis=0; if (tmp) return true; } } return false; } int solve(int n, int k){ int l,r,mid; l=0, r=k+1; while (l<r){ mid=(l+r)>>1; if ( dfs(n,k,0,mid,0) ) r=mid; else l=mid+1; } if (l==k+1) return -1; else return l; } int main(){ int i,k,n; while ( scanf("%d",&n), n ){ scanf("%d",&k); for (i=0; i<k; i++) scanf("%d %d",&V[i].x,&V[i].y); for (i=0; i<k; i++) scanf("%d",&V[i].r); printf("%d\n",solve(n,k)); } return 0; }