首页 > 代码库 > CUGBACM_Summer_Tranning5

CUGBACM_Summer_Tranning5

A.Number Assignment

UvaLive6434

简单题

#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

UvaLive6436

据说这是基础的树形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

UvaLive6437

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!

UvaLive6439

一直在用暴力做,但是一直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;
}