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;
}