The number of problem solution CSP2019 tree

Face problems
that are typical of a positive solution part of sub-inspired theme.

So let's look at two parts points.

FIG Chrysanthemum Part 1

This should be in addition to the violence think the best part of a file divided.

FIG above (on the node number has been omitted), if we successively deleting edges (2) (1) (3) (4), the numbers on the 2-point operation will go to No. 1 after point 1 dot number will go on 3-point, 3-point digital push to go on ...... so tired 4 points. Then we become equivalent to five nodes connected one ring (5 -> 2 -> 1--> 3 -> 4 -> 5), each of the numbers will go to the next node on the ring junction point up we claim that the resulting arrangement can lexicographically smallest ring. So we bit by bit greedy, first node is located 1 to select it the next point on the ring of which one, where the node numbers by 2 election, and so on. Each node can be selected from the minimum reference in lawful. Specific details may be found in the code.

Part1 Code:

#include<bits/stdc++.h>
using namespace std;
#define N 4007
#define mem(x) memset(x,0,sizeof(x))
int p[N],ans[N],vis[N];
int fa[N];
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    mem(vis);
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    int x,y;
    for(int i=1;i<n;i++)
        scanf("%d%d",&x,&y);
    for(int i=1;i<=n;i++)
    {
        int x=p[i];
        for(int j=1;j<=n;j++)
        {
        if(!vis[j]&&(i==n||find(x)!=find(j)))
        {
            ans[i]=j;
            fa[find(x)]=find(j);
            vis[j]=1;
            break;
        }
        }
    }
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    printf("\n");
    }
    return 0;
}

Part2 chain

This part of the close relationship and positive solutions, introduced the topological order restrictions in the title of the model to describe.

Where the nodes in parentheses are the numbers on the node.
If you want to go to number 1 No. 1 node up how to do?
Then we can in turn be deleted No. (2) (3) side, then the number 1 on the last number in 1:00.
As long as this can it?
In fact, this also implies two conditions, that is, the edge (1) must be deleted after (2) and (4) must be removed before (3), or where it should not be the number 1 in place.
If we get one of each side of priority , the priority of a big first cut, then the priority of the magnitude relationship between the four sides is: (1) <(2)> (3) <(4)
so that we can ensure that the digital No. 1 in the final 1:00, in addition to bit by bit greedy because we want to, so on this basis, we also want to be able to number 2 on the 2nd node.
But is it possible to do?
Found that such is not possible, because the number 2 to the number 2 to make the point, it must satisfy the priority (3)> (2), with a number of conditions are in conflict, so not.
So we got this part of the algorithm:
1 n-by-bit digital to digital from greedy, each time you select a digit current can reach, not conflict with the previous conditions, the smallest node labels, as a node where the final figure. Then join the newly created conditions.
Specific implementations may maintain a flag value in each of the nodes 0, 1, respectively, there is no priority restriction between the left and right sides of the two nodes is greater than the left to the right, the right greater than left. Then find the qualifying each point from the current position to the right and left digital location, then update the tag value corresponding to the new conditions. See in particular code.

Part2 Code:

#include<bits/stdc++.h>
using namespace std;
#define N 4007
int hd[N],pre[N],to[N],num,tag[N],pos[N],id[N],p[N],d[N],cnt,ans[N];
void adde(int x,int y)
{
    num++;pre[num]=hd[x];hd[x]=num;to[num]=y;
}
void dfs(int v,int f)
{
    id[++cnt]=v,pos[v]=cnt;
    for(int i=hd[v];i;i=pre[i])
    {
    int u=to[i];
    if(u==f)continue;
    dfs(u,v);
    }
}
#define mem(x) memset(x,0,sizeof(x))
int main()
{
    int n;
    int t;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d",&n);
    mem(hd),mem(tag),mem(d);
    num=0,cnt=0;
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        adde(x,y),adde(y,x);
        d[x]++,d[y]++;
    }
    int rt=0;
    for(int i=1;i<=n ;i++)
        if(d[i]==1)rt=i;
    dfs(rt,0);
    for(int i=1;i<=n;i++)
    {#include<bits/stdc++.h>
using namespace std;
#define N 20007
#define mem(x) memset(x,0,sizeof(x))
int hd[N],pre[N],to[N],num,fa[N],sz[N],d[N],p[N],ver;
bool in[N],out[N];
void adde(int x,int y)
{
    num++;pre[num]=hd[x];hd[x]=num;to[num]=y;
}
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
    int u=find(x),v=find(y);
    fa[u]=v,sz[v]+=sz[u];
    out[x]=in[y]=1;
}
bool check(int x,int y,int l)
{
    if(in[y]||out[x])return false;
    int u=find(x),v=find(y);
    if(u==v&&sz[u]!=l)return false;
    return true;
}
void dfs1(int v,int f)
{
    if(f!=v&&check(f,v,d[v]+1))ver=min(ver,v);
    for(int i=hd[v];i;i=pre[i])
    {
    int u=to[i];
    if(i==f)continue;
    if(check(f,i,d[v]+1))
    {
        dfs1(u,i^1);
    }
    }
}
bool dfs2(int v,int f,int p)
{
    if(v==p)
    {
    merge(f,v);
    return true;
    }
    for(int i=hd[v];i;i=pre[i])
    {
    int u=to[i];
    if(i==f)continue;
    if(dfs2(u,i^1,p))
    {
        merge(f,i);
        return true;
    }
    }
    return false;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d",&n);
    mem(hd),mem(in),mem(out),mem(d);
    num=(n+1)/2*2+1;
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        d[x]++,d[y]++;
        adde(x,y),adde(y,x);
    }
    for(int i=1;i<=num;i++)
        fa[i]=i,sz[i]=1;
    for(int i=1;i<=n;i++)
    {
        int v=p[i];
        ver=n+1;
        dfs1(v,v);
        dfs2(v,v,ver);
        printf("%d ",ver);
    }
    printf("\n");
    }
    return 0;
}

        int x=p[i],b=pos[x];
        int mi=n+1;
        if(tag[b]!=1)
        {
        for(int j=b+1;j<=n;j++)
        {
            if(tag[j]!=1)mi=min(mi,id[j]);
            if(tag[j]==2)break;
        }
        }
        if(tag[b]!=2)
        {
        for(int j=b-1;j>=1;j--)
        {
            if(tag[j]!=2)mi=min(mi,id[j]);
            if(tag[j]==1)break;
        }
        }
        if(pos[mi]>b)
        {
        for(int j=b+1;j<=pos[mi]-1;j++)tag[j]=1;
        tag[b]=tag[pos[mi]]=2;
        }
        else
        {
        for(int j=pos[mi]+1;j<b;j++)tag[j]=2;
        tag[pos[mi]]=tag[b]=1;
        }
        tag[1]=tag[n]=0;
        ans[i]=mi;
    }
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    printf("\n");
    }
    return 0;
}

Part3 correct answer

In fact, we have seen from the second portion, shaped as a digital number x to node y to satisfy the conditions required for the priority can be described as a series of edge magnitude relation (here, a priority order is actually a topology) and we can put these conditions on a node, the node representing the relationship between the size of the adjacent edges of all is how, that will have a size relationship between only adjacent to the same side of the node restrictions . So how do we put algorithms in the chain expanded to the general tree it?

If you want to have a digital number from 1 pm to 3:00, then the conditions need to be met in two ways:

  1. (3) the priority station 1 is the largest abutting edges, (6) Priority Point 3 is the smallest adjacent sides;
  2. (3) greater than the priority (6);

For condition 2, this was not sufficient, because then deleted if End (3) and then delete (4) it is not right. That is deleted after completion of (3) to be deleted immediately (6)
This is equivalent to the constraint and the No. 2 points adjacent sides are sized according to the priority, then (3) and (6) must be adjacent, and (3) in the front (6).
How to do this? This discovery let the two sides adjacent condition is already discussed in the first part of the daisy chart too, as with disjoint-set to judge, but Part1 only used a disjoint-set, and now we to maintain the relationship between the size of each point around the edge, so to open a point for each disjoint-set.
For Condition 1, my approach is for each disjoint-set built a virtual point, if the priority biggest one side, then the virtual point to it even an edge, an edge if the priority of the smallest, by it to a virtual point even edge, so that the code may directly set a section Part1.
Greedy process is similar Part2 then, each time starting from a point of traversing the whole tree, each side would take a judge for themselves, and then on a path to be modified.

Part3 Code:

#include<bits/stdc++.h>
using namespace std;
#define N 20007
#define mem(x) memset(x,0,sizeof(x))
int hd[N],pre[N],to[N],num,fa[N],sz[N],d[N],p[N],ver;
bool in[N],out[N];
void adde(int x,int y)
{
    num++;pre[num]=hd[x];hd[x]=num;to[num]=y;
}
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
    int u=find(x),v=find(y);
    fa[u]=v,sz[v]+=sz[u];
    out[x]=in[y]=1;
}
bool check(int x,int y,int l)
{
    if(in[y]||out[x])return false;
    int u=find(x),v=find(y);
    if(u==v&&sz[u]!=l)return false;
    return true;
}
void dfs1(int v,int f)
{
    if(f!=v&&check(f,v,d[v]+1))ver=min(ver,v);
    for(int i=hd[v];i;i=pre[i])
    {
    int u=to[i];
    if(i==f)continue;
    if(check(f,i,d[v]+1))
    {
        dfs1(u,i^1);
    }
    }
}
bool dfs2(int v,int f,int p)
{
    if(v==p)
    {
    merge(f,v);
    return true;
    }
    for(int i=hd[v];i;i=pre[i])
    {
    int u=to[i];
    if(i==f)continue;
    if(dfs2(u,i^1,p))
    {
        merge(f,i);
        return true;
    }
    }
    return false;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d",&n);
    mem(hd),mem(in),mem(out),mem(d);
    num=(n+1)/2*2+1;
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        d[x]++,d[y]++;
        adde(x,y),adde(y,x);
    }
    for(int i=1;i<=num;i++)
        fa[i]=i,sz[i]=1;
    for(int i=1;i<=n;i++)
    {
        int v=p[i];
        ver=n+1;
        dfs1(v,v);
        dfs2(v,v,ver);
        printf("%d ",ver);
    }
    printf("\n");
    }
    return 0;
}

Summary: This is the question we can find positive solutions to this problem with some points are closely linked, if not thinking of some points, is difficult to directly think of positive solutions. This inspired us to think of the time when no direct positive solution, can consider this question a number of sub-section, sub-section to find the link between the positive solution, and then a roundabout way to find positive solutions. Some people were too seek positive solutions, skip part points to think positive solution, the result will not be positive solutions.For example, the author is such a negative example

Guess you like

Origin www.cnblogs.com/lishuyu2003/p/12077009.html