A.Number Assignment
简单题
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 50100 #define eps 1e-7 #define INF 0x7FFFFFFF #define seed 131 #define mod 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int a[150],b[150]; int main(){ int k = 1,t,i,j,n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(i=0;i<n;i++) scanf("%d",&a[i]); sort(a,a+n); int sum = 0; for(i=0;i<n-1;i++){ b[i] = a[i+1] - a[i]; sum += b[i]; } sort(b,b+n-1); // for(i=0;i<n-1;i++) cout<<b[i]<<" "; // cout<<endl; for(i=0;i<m-1;i++){ sum -= b[n-i-2]; } printf("Case #%d: %d\n",k++,sum); } return 0; }
C.The Busiest City
据说这是基础的树形DP,ORZ。
根据邻接表的信息,设一个根节点开始dfs,找到当前根有多少子集,和不在当前根子集中的节点做乘法,就是当前根的子集和外面各个点的路径数,就是经过当前根的一部分次数,设为tot1。然后再在根内,假设这个根是A,找到A的每一个子集和A内其他子集的乘积,这是根内的路径个数,也是经过A的另一部分次数tot2,但是每一个子集都和其他子集做乘法,相当于乘了两遍,最后再除以2,和原来的次数tot1相加就是总的经过A的路径数目。
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 50100 #define eps 1e-7 #define INF 0x7FFFFFFF #define seed 131 #define mod 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node{ int u,next; }edge[50100]; int head[20100],sum[20100]; int n,ans,cnt; void add_edge(int a,int b){ edge[cnt].u = b; edge[cnt].next = head[a]; head[a] = cnt++; } void dfs(int pre,int rt){ sum[rt] = 1; int tot = 0; int tot2 = 0; int i,j; for(i=head[rt];i!=-1;i=edge[i].next){ int u = edge[i].u; if(u==pre) continue; dfs(rt,u); sum[rt] += sum[u]; } tot = (sum[rt]-1) * (n-sum[rt]); for(i=head[rt];i!=-1;i=edge[i].next){ int u = edge[i].u; if(u==pre) continue; tot2 += sum[u] * (sum[rt]-sum[u]-1); } tot += tot2 / 2; if(tot>ans) ans = tot; } int main(){ int t,i,j,a,b,k=1; scanf("%d",&t); while(t--){ memset(head,-1,sizeof(head)); ans = 0; cnt = 0; scanf("%d",&n); for(i=1;i<n;i++){ scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } dfs(1,1); printf("Case #%d: %d\n",k++,ans); } return 0; }
D.Power Plant
K个源点的最小生成树,不要想复杂了,把K个源点合并,还是个最小生成树。。
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 200100 #define eps 1e-7 #define INF 0x7FFFFFFF #define seed 131 #define mod 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node{ int u,v,dis; }edge[MAXN]; int father[210],flag[210],num[210]; int aa[210]; int n,m,cnt,ans,k; bool cmp(node x,node y){ return x.dis<y.dis; } int find(int x){ int t = x; while(t!=father[t]) t = father[t]; int k = t; while(k!=t){ int temp = father[k]; father[k] = t; k = temp; } return t; } void gao(){ int i,j; for(i=0;i<m;i++){ if(cnt>=n-k) break; int a = find(edge[i].u); int b = find(edge[i].v); if(a!=b){ father[a] = b; ans += edge[i].dis; cnt++; } } } int main(){ int i,j,t,cas = 1,bb; scanf("%d",&t); while(t--){ ans = 0; memset(flag,0,sizeof(flag)); scanf("%d%d%d",&n,&m,&k); cnt = 0; for(i=1;i<=n;i++){ father[i] = i; } for(i=0;i<k;i++){ scanf("%d",&aa[i]); for(j=0;j<i;j++){ int ta = find(aa[i]); int tb = find(aa[j]); if(ta!=tb){ father[ta] = tb; } } } for(i=0;i<m;i++){ scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].dis); } sort(edge,edge+m,cmp); gao(); printf("Case #%d: %d\n",cas++,ans); } return 0; } /* 999 6 5 2 3 6 1 6 2 1 2 1 2 3 4 3 4 6 4 5 3 12 */
F.Pasti Pas!
一直在用暴力做,但是一直WA,baoge的暴力用的string,很简洁也很好理解,我随机生成了N组数据,试了N^2遍,每次我的程序和baoge的程序输出结果都一样,可提交就是WA,没想明白错在哪里。。后来用hash做的,枚举前一段和后一段等长的字串hash值是否相等
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 200100 #define eps 1e-7 #define INF 0x7FFFFFFF #define seed 131 #define mod 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 char str[50010]; ull base[50010],Hash[50010]; int main(){ int t,i,j,k=1; scanf("%d",&t); base[0] = 1; for(i=1;i<=50005;i++) base[i] = base[i-1] * seed; while(t--){ scanf("%s",str); int l = strlen(str); int l2 = l / 2; Hash[l] = 0; for(i=l-1;i>=0;i--){ Hash[i] = Hash[i+1] * seed + str[i] - 'A'; } ull p1, p2; int ans = 0; int ll1,ll2,rr1,rr2; ll1 = 0,ll2 = l-1,rr1 = 1,rr2 = l; for(i=0;i<l2;i++){ p1 = Hash[ll1] - Hash[rr1] * base[rr1-ll1]; p2 = Hash[ll2] - Hash[rr2] * base[rr2-ll2]; if(p1==p2){ ans += 2; ll1 = rr1; rr2 = ll2; } rr1++; ll2--; } if(rr1-ll1>1||rr2>ll1) ans++; printf("Case #%d: %d\n",k++,ans); } return 0; }
CUGBACM_Summer_Tranning5,布布扣,bubuko.com
时间: 2024-10-14 03:48:18