contest20151123

跪了跪了。。没事反正跪习惯了
呃是jsoi2015 day1

T1

f[i]表示以i为根的子树的答案。
u[i]表示以i为根的子树的答案是否unique。
嗯。。f贪心一下就可以了。
u:设贪心了k个儿子
- 如果取的k个中有答案不唯一的,则答案不唯一
- 如果前k个中有0,则答案不唯一(啊我错了)
- 如果第k个和第k+1个相同,则答案不唯一(当然儿子数要>=k+1)

T2

//听说是道不难死你也要烦死你的题。。窝太懒先留个坑
嗯。。矩阵hash吧

T3

去掉假节点很简单,然后就是无根树同构。
于是只要选几个东西hash一下,正确性要求不高,毕竟只有20棵树。。
然而我选了度数,自然被卡飞(30分不错耶)。。可以拓扑每层节点数,能A
然后是正解
窝萌只会有根树同构是不是,那么有许多解决方案
- 求树的重心,如果有两个,这两个中间加个点作为重心
- 拓扑到只剩1个或2个点。2个点分别做,再hash起来
这方法极不推荐(小心码长被人碾)
于是lh一语道破(太精妙了我膜拜不已)
无向图同构:给每个点一个初始hash值1。每轮中,对于每个点,取出其邻点的hash值,sort之后hash起来,作为这个点的新hash值。若干轮(实际是2轮?数据水了吧)之后,将所有点的值再sort,hash,代表这个图。
然后就没有了。。
嗯。。zj18au,js5au,js第五170。。
%NiroBC190

上代码
T1

#include<bits/stdc++.h>
using namespace std;
#define SC scanf
#define U_(i,a,b) for(int i=a;i<=b;i++)
#define D_(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
#define MK make_pair
#define A first
#define B second
const int N=200000;
struct EG{int a,b;}eg[N<<1];
int head[N],en;
int ans[N];
int b[N],n;
bool uni[N];
void add(int u,int v){
    eg[++en]=(EG){v,head[u]};
    head[u]=en;
}
void dfs(int u,int fa){
    priority_queue<pair<int,int> >q;
    int son=0;
    bool flg=0;
    for(int e=head[u];e;e=eg[e].b){
        int v=eg[e].a;
        if(v==fa)continue;
        dfs(v,u);
        q.push(MK(ans[v],v));
        if(ans[v]==0)flg=1;
        son++;
    }
    int tmp;
    U_(i,1,min(son,b[u]-1)){
        if(q.top().A<0)break;
        if(q.top().A==0){flg=1;break;}
        tmp=q.top().A;
        flg|=uni[q.top().B];
        {ans[u]+=q.top().A;q.pop();}
    }
    if(!q.empty()&&tmp==q.top().A)flg=1;
    uni[u]=flg;
}
int main(){//freopen("salesman.in","r",stdin);freopen("salesman.out","w",stdout);
    SC("%d",&n);
    ans[1]=0;b[1]=1000000000;
    U_(i,2,n)SC("%d",&ans[i]);
    U_(i,2,n)SC("%d",&b[i]);
    U_(i,1,n-1){
        int u,v;
        SC("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,1);
    printf("%d\n",ans[1]);
    if(!uni[1])puts("solution is unique");else puts("solution is not unique");
}

T2//是抄来的。。

#include<bits/stdc++.h>
using namespace std;
#define SC scanf
#define U_(i,a,b) for(int i=a;i<=b;i++)
#define D_(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
#define MK make_pair
#define A first
#define B second
#define CK(x) check_##x
#define CHK(x,len,i,j) check_##x(len,i,j)
typedef unsigned int uint;
typedef unsigned long long ull;
const int N=511,d1=233,d2=2333;
uint h[N][N],h0[N][N],h1[N][N],h2[N][N],h3[N][N],h4[N][N],h5[N][N],pow1[N],pow2[N];
int n;
void init(){
    SC("%d",&n);
    static char s[N];
    U_(i,1,n){
        SC("%s",s+1);
        U_(j,1,n)h[i][j]=s[j]-'0';
    }
    pow1[0]=1;U_(i,1,n)pow1[i]=pow1[i-1]*d1;
    pow2[0]=1;U_(i,1,n)pow2[i]=pow2[i-1]*d2;
}
void build(){
    U_(i,1,n)U_(j,1,n)if(h[i][j])
        h0[i][n-j+1]=h1[n-i+1][j]=h2[j][i]=h3[n-j+1][n-i+1]=h4[j][n-i+1]=h5[n-i+1][n-j+1]=1;
}
void get(uint a[][N]){
    U_(i,1,n){
        int p=pow1[n-i];
        U_(j,1,n)a[i][j]=a[i][j]*p*pow2[n-j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
    }
}
void gethash(){get(h),get(h0),get(h1),get(h2),get(h3),get(h4),get(h5);}
uint gao(uint h[][N],int len,int x,int y){return (h[x][y]-h[x-len][y]-h[x][y-len]+h[x-len][y-len])*pow1[x]*pow2[y];}
bool check_0(const int len,const int x,const int y){
    uint tmp=gao(h,len,x,y);
    return tmp==gao(h0,len,x,n-y+len)||tmp==gao(h1,len,n-x+len,y)||tmp==gao(h2,len,y,x)||tmp==gao(h3,len,n-y+len,n-x+len);
}
bool check_90(int &len,int &x,int &y){return gao(h,len,x,y)==gao(h4,len,y,n-x+len);}
bool check_180(int &len,int &x,int &y){return gao(h,len,x,y)==gao(h5,len,n-x+len,n-y+len);}
bool check_4(int &len,int &x,int &y){return CHK(180,len,x,y)&&CHK(0,len,x,y);}
bool check_8(int &len,int &x,int &y){return CHK(90,len,x,y)&&CHK(0,len,x,y);}
template<class T>bool check(int len,T f){
    U_(i,len,n)U_(j,len,n)if(f(len,i,j))return 1;
    return 0;
}
template<class T>int calc(T f){
    int l=1,r=n/2,mid;
    while(l<=r){
        mid=l+r>>1;
        if(check(2*mid,f))l=mid+1;else r=mid-1;
    }
    l--;if(!check(2*l+1,f))return 2*l;
    r=n/2;
    while(l<=r){
        mid=l+r>>1;
        if(check(2*mid+1,f))l=mid+1;else r=mid-1;
    }
    l--;return 2*l+1;
}
void solve(){
    int a=calc(CK(8)),b=calc(CK(90)),c=calc(CK(4)),d=calc(CK(180)),e=calc(CK(0));
    printf("%d %d %d %d ",a,b,c,d);
    if(b==7 && c==8 && d==8 && e==9)puts("8");else printf("%d\n",e);
}
int main(){init();build();gethash();solve();}

T3

#include<bits/stdc++.h>
using namespace std;
#define SC scanf
#define U_(i,a,b) for(int i=a;i<=b;i++)
#define D_(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
#define MK make_pair
#define A first
#define B second
const int N=10010;
struct EG{int a,b,c;}eg[N<<1];
int head[N],en;
int fa[N];
int b[N];
int init[N];
int f[N],n,m,cnt,tmp,B[N];
int sf(int u){
    return u==f[u]?u:f[u]=sf(f[u]);
}
void add(int u,int v){
    eg[++en]=(EG){v,head[u],u};
    head[u]=en;
}
int read(){
    char ch;
    int v;
    for(ch=0; ch<48||ch>57; ch=getchar());
    for(v=0; ch>=48&&ch<=57; ch=getchar()) v=(v<<1)+(v<<3)+ch-48;
    return v;
}
void dfs(int u){
    for(int e=head[u];e;e=eg[e].b){
        int v=eg[e].a;
        if(v==fa[u])continue;
        fa[v]=u;
        if(init[u]==2)f[sf(v)]=sf(u);
        dfs(v);
    }
}
pair<int,int>fuck[N];
int ha[N];
priority_queue<int>st[N];
int main(){
    m=read();
    U_(l,1,m){
        n=read();
        en=0;
        U_(i,1,n)head[i]=0;
        U_(i,1,n)init[i]=0;
        U_(i,1,n-1){
            int u,v;
            u=read();v=read();
            add(u,v);
            add(v,u);
            init[u]++;
            init[v]++;
        }
        U_(i,1,n)f[i]=i;
        int shit=0;
        U_(i,1,n)if(init[i]!=2){shit=i;break;}
        fa[shit]=shit;
        dfs(shit);
        U_(i,1,n)b[i]=sf(i);
        U_(i,1,n)B[i]=b[i];
        sort(B+1,B+n+1);
        cnt=unique(B+1,B+n+1)-B-1;
        U_(i,1,n)b[i]=lower_bound(B+1,B+cnt+1,b[i])-B;
        en=0;
        U_(i,1,2*(n-1))if(b[eg[i].a]!=b[eg[i].c])eg[++en].a=b[eg[i].a],eg[en].c=b[eg[i].c];
        U_(i,1,cnt)ha[i]=1;
        U_(i,1,2){
            U_(j,1,cnt)while(!st[j].empty())st[j].pop();
            U_(j,1,2*(cnt-1))st[eg[j].c].push(ha[eg[j].a]);
            U_(j,1,cnt){
                ha[j]=1;
                while(!st[j].empty()){
                    ha[j]=(ha[j]*10007^st[j].top()+6667)%10009;
                    st[j].pop();
                }
            }
        }
        fuck[l].B=0;
        sort(ha+1,ha+cnt+1);
        U_(i,1,cnt)fuck[l].B=(fuck[l].B*6667%10009+ha[i])%10009;
        fuck[l].A=cnt;
    }
    sort(fuck+1,fuck+m+1);
    m=unique(fuck+1,fuck+m+1)-fuck-1;
    printf("%d\n",m);
    U_(i,1,m-1)printf("%d ",fuck[i].A);
    printf("%d\n",fuck[m].A);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值