GCJ2019 Round1A AC

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IDrandom/article/details/89409764

A.pylons
小数据暴力,大数据根据ore定理用延长通路法构造解,这里参考了
https://www.cnblogs.com/zhj5chengfeng/p/3233992.html
这篇blog的总结,赛内我犯了sb错误,把下标当数用了当场GG,然后,然后就没了

#include<bits/stdc++.h>
using namespace std;
struct edge{
    int v,nxt;
}e[200000];
int h[405];
int vis[405];
int deg[405];
stack<int>ans;
int cnt=0;
void init(){
    memset(e,-1,sizeof e);
    memset(h,-1,sizeof h);
    memset(vis,0,sizeof vis);
    memset(deg,0,sizeof deg);
    while(!ans.empty())ans.pop();
    cnt=0;
}
void add(int u,int v){
    e[cnt].v=v;
    e[cnt].nxt=h[u];
    h[u]=cnt++;
}
struct Hamilton_Circuit {
    static const int N=405;

    bool G[N][N], vs[N];
    int n, next[N], head, tail;

    void init(int _n) {
        n=_n;
        memset(G, 0, sizeof G);
        for(int i=0;i<_n;i++){
            for(int j=h[i];~j;j=e[j].nxt){
                G[i][e[j].v]=1;
            }
        }
    }
    void DFS_Head(int u) {
        vs[u]=1;
        for(int i=0; i<n; i++) if(G[i][u] && !vs[i]) {
            next[i]=u;
            DFS_Head(i);
            return;
        }
        head=u;
    }

    void DFS_Tail(int u) {
        vs[u]=1;
        for(int i=0; i<n; i++) if(G[u][i] && !vs[i]) {
            next[u]=i;
            DFS_Tail(i);
            return;
        }
        tail=u;
    }

    void Reverse(int u) {
        for(int i=next[u], temp, last=-1; i!=-1; i=temp) {
            temp=next[i];
            next[i]=last;
            last=i;
        }
        int temp=tail;
        tail=next[u];
        next[u]=temp;
    }

    int Find(int u) {
        for(int i=head; i!=-1; i=next[i]) {
            if(G[u][next[i]]) return i;
        }
        return -1;
    }

    bool Extend(int u) {
        if(G[u][head]) {
            next[u]=head;
            return 1;
        }
        int pre=Find(u);
        if(pre==-1) return 0;
        next[u]=next[pre];
        next[tail]=head;
        next[tail=pre]=-1;
        return 1;
    }

    void Solve() {
        memset(next, -1, sizeof next);
        memset(vs, 0, sizeof vs);
        DFS_Head(0), DFS_Tail(0);
        int Len=1;
        for(int i=head; i!=tail; i=next[i], Len++);
        for(int i; 1; ) {
            if(!G[tail][head]) {
                for(i=next[head]; !(G[i][tail] && G[next[i]][head]); i=next[i]);
                Reverse(i);
            }
            if(Len==n) break;
            for(i=0; i<n; i++) if(!vs[i] && Extend(i)) {
                head=i, vs[i]=1, Len++;
                break;
            }
        }
    }

    void PRINT(int c) {
        for(int i=head; head!=0; i=next[i]) {
            next[tail]=head;
            tail=head;
            head=next[head];
            next[tail]=-1;
        }
        for(int i=head; i!=-1; i=next[i]) {
            printf("%d %d\n", i/c+1,(i%c)+1);
            //if(next[i]==-1) printf("1 1\n");
        }
    }
};

Hamilton_Circuit fuck;

int dfs(int rt,int cnt,int n){
    //printf("%d %d\n",rt,cnt);
    if(cnt==n){
        ans.push(rt);
        return 1;
    }
    for(int i=h[rt];~i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(!vis[v]){
            vis[v]=1;
            if(dfs(v,cnt+1,n)){
                ans.push(rt);
                return 1;
            }
            vis[v]=0;
        }
    }
    return 0;
}
int main(){
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        int r,c,n;
        init();
        scanf("%d%d",&r,&c);
        n=r*c;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                int ux=i/c,uy=i%c;
                int vx=j/c,vy=j%c;
                if(ux==vx||uy==vy||(ux-uy)==(vx-vy)||(ux+uy)==(vx+vy))continue;
                deg[i]++;deg[j]++;
                add(i,j);add(j,i);
            }
        }
        int mn=n;
        for(int i=0;i<n;i++){
            mn=min(mn,deg[i]);
        }
        printf("Case #%d: ",cas);
        if(mn>=n/2){//construct
            puts("POSSIBLE");
            fuck.init(n);
            fuck.Solve();
            fuck.PRINT(c);
        }else{//search
            int f=0;
            for(int i=0;i<n;i++){
                vis[i]=1;
                if(dfs(i,1,n)){
                    f=1;
                    break;
                }
                vis[i]=0;
            }
            if(!f)puts("IMPOSSIBLE");
            else {puts("POSSIBLE");
            while(!ans.empty()){
                int qq=ans.top();
                ans.pop();
                printf("%d %d\n",qq/c+1,(qq%c)+1);
            }
            }
        }
    }
    return 0;
}

C.Alien Rhyme
反向构造一颗字典树,对于一个节点,这层最多只能分出去一对,那么当前子树如果<4个就直接分割出去一对,dfs跑一跑就好了

#include<bits/stdc++.h>
using namespace std;
struct node{
    int c[26];
    int ans;
    int sum;
}tree[100000];
int cnt=0;
char str[55];
void init(){
    memset(tree,0,sizeof tree);
    cnt=0;
}
void Insert(int rt,int p){
    tree[rt].sum++;
    if(p==-1)return;
    int q=str[p]-'A';
    if(tree[rt].c[q]){
        Insert(tree[rt].c[q],p-1);
    }else{
        tree[rt].c[q]=++cnt;
        Insert(cnt,p-1);
    }
}
void solve(int rt){
    if(rt&&tree[rt].sum<=3){
        tree[rt].ans=tree[rt].sum/2;
        return ;
    }
    for(int i=0;i<26;i++){
        int son=tree[rt].c[i];
        if(!son)continue;
        solve(son);
        tree[rt].ans+=tree[son].ans;
    }
    int lft=tree[rt].sum-(tree[rt].ans<<1);
    if(rt&&lft>=2){
        tree[rt].ans++;
    }

}
int main(){

    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        int n;
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",str);
            Insert(0,strlen(str)-1);
        }
        solve(0);
        printf("Case #%d: %d\n",cas,tree[0].ans*2);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/IDrandom/article/details/89409764
ac