JZOJ5853. 【NOIP2018提高组模拟9.6】老大

JZOJ5853. 【NOIP2018提高组模拟9.6】老大_第1张图片
JZOJ5853. 【NOIP2018提高组模拟9.6】老大_第2张图片

题解

如果只放一个点,很显然就是放在直径的中点上面,这样一定是最优的,
而现在题目要求断开一条边,然后使得两个部分的最长直径最短。
考虑断开这条边的位置,一定是在原来那棵树的直径上面。
于是呢,就把直径抽出来,
求出断开每一条边的上半部分跟下半部分的直径分别是多少,
然后组合一下就好了。

code

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ll long long
#define N 13
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return aabs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

int a[N][N],b[N][N],ans[N][N],num;
int bel[N][N],s[N*N],si[N*N],m,n;
int fx[4][2]={{-1,0},{0,-1},{0,1},{1,0}};
bool t1[N][10],t2[N][10];

struct node
{
    int x,y,si,cnt;
}w[N*N];

bool cmp(node a,node b) 
{
    return a.sivoid dfs(int x,int y,int t)
{
    int xx,yy;
    for(int i=0;i<4;i++)
    {
        xx=x+fx[i][0];
        yy=y+fx[i][1];
        if(xx<1 || yy<1 || xx>n ||yy>n)continue;
        if(!bel[xx][yy] && a[xx][yy]==t)si[bel[xx][yy]=bel[x][y]]++,dfs(xx,yy,t);
    }
}

bool check()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(ans[i][j]return 0;
            if(ans[i][j]>b[i][j])return 1;
        }
    return 0;
}

void dg(int now)
{
    int id,x=w[now].x,y=w[now].y;
    if(now>n*n)
    {
        num++;
        if(check())memcpy(ans,b,sizeof(ans));
        return;
    }
    for(int i=1;i<10;i++)
        if(t1[x][i] && t2[y][i])
        {
            id=bel[x][y];
            if(s[id]%i)continue;
            if(si[id]==1 && (s[id]^i))continue;
            si[id]--;s[id]=s[id]/i;
            b[x][y]=i;t1[x][i]=t2[y][i]=0;
            dg(now+1);
            si[id]++;s[id]=s[id]*i;
            t1[x][i]=t2[y][i]=1;
        }
}

int main()
{
    freopen("kenken.in","r",stdin);
    freopen("kenken.out","w",stdout);

    read(n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            read(a[i][j]);

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(!bel[i][j])
            {
                s[bel[i][j]=++m]=a[i][j];
                si[m]=1;
                dfs(i,j,a[i][j]);
            }
            w[i*n-n+j].x=i;
            w[i*n-n+j].y=j;
            w[i*n-n+j].si=a[i][j]; 
            w[i*n-n+j].cnt=bel[i][j]; 
        }

    sort(w+1,w+1+n*n,cmp);
    memset(t1,1,sizeof(t1));
    memset(t2,1,sizeof(t2));

    ans[1][1]=N,dg(1);
    write(num);P('\n');
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            write(ans[i][j]),P(' ');
        P('\n');
    }

    return 0;
}

你可能感兴趣的:(题解,树的直径,DFS)