ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

五一欢乐赛 方程的解 染色 光 无向图问题

2022-05-02 02:31:19  阅读:187  来源: 互联网

标签:int 染色 make t1 无向 五一 && pair dir


比赛链接

考场上顺序开题。

\(\mathrm{A.}\mathbb{方程的解}\):\(\mathrm{exgcd}\) 板子

\(\mathrm{B.}\mathbb{染色}\):树形 \(\mathrm{dp}\)

\(\mathrm{C.}\mathbb{光}\):优化 \(\mathrm{dfs}\)

\(\mathrm{D.}\mathbb{无向图问题}\):这道题说了个啥?

打开发现又是原题大赛,除了 \(\mathrm{D}\) 都是见过的原题,于是果断的先打了 \(\mathrm{A}\) 和 \(\mathrm{C}\)。

打 \(\mathrm{A}\) 时没有一遍过,细节太多太杂,调了大概一个小时才过,打 \(C\) 时有一个小细节写挂了,快结束才改过来,幸好过了。

结果比较水的 \(\mathrm{B}\) 后来没时间打了,所以尽管过了 \(\mathrm{C}\) 分还是在第二档的水平。

以后一眼题先写,别拖到最后。

估分:\(100+0+100+0=200\)

实际:\(100+0+100+0=200\)

还是说正解吧(

A.方程的解

正解

很明显先用 \(\mathrm{exgcd}\) 算出来判断是否有解,并算出一组可行解。然后用这组解推出当 \(x\) 为最小正整数解时的 \(y\) 的值,接下来判断有几组正整数解就行了。

可以在求出最小正整数解之前先根据 \(a,b,c\) 的符号来判断是否会有 \(x,y\) 同时为正整数的情况,这样可以在后面判断负数时较为容易一些。

时间复杂度:\(O(Tn\log n)\)

code
#include<bits/stdc++.h>
using namespace std;
int t;
long long a,b,c,x,y;
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    long long d=exgcd(b,a%b,x,y);
    long long z=x;
    x=y;
    y=z-y*(a/b);
    return d;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&a,&b,&c);
        if(a==0&&b==0)
        {
            if(c==0) printf("ZenMeZheMeDuo\n");
            else printf("0\n");
            continue;
        }
        if(b==0)
        {
            if(c%a==0&&c*a>0) printf("ZenMeZheMeDuo\n");
            else printf("0\n");
            continue;
        }
        if(a==0)
        {
            if(c%b==0&&c*b>0) printf("ZenMeZheMeDuo\n");
            else printf("0\n");
            continue;
        }
        if((a>0&&b>0&&c<0)||(a<0&&b<0&&c>0))
        {
            printf("0\n");
            continue;
        }
        if(a<0&&b<0) a=-a,b=-b,c=-c;
        long long d=exgcd(a,b,x,y),k;
        if(c%d!=0)
        {
            printf("0\n");
            continue;
        }
        if((a>0&&b<0)||(a<0&&b>0))
        {
            printf("ZenMeZheMeDuo\n");
            continue;
        }
        x*=c/d,y*=c/=d;
        a/=d,b/=d;
        if(x<=0) k=ceil((1.0-x)/b),x+=b*k,y-=a*k;
        else k=(x-1)/b,x-=b*k,y+=a*k;
        if(y>0)
        {
            if((y-1)/a+1>65535) printf("ZenMeZheMeDuo\n");
            else printf("%lld\n",(y-1)/a+1);
        }
        else printf("0\n");
    }
    return 0;
}

B.染色

正解

首先可以不算任何两个点之间的距离之和,只需算每条边被经过的次数。再根据乘法原理,每一条边的经过次数就等于它两侧的黑色个数之积加上白色个数之积,这样只需在树形 \(\mathrm{dp}\) 时枚举以 \(u\) 为根的子树内恰好有 \(j\) 个点为黑色的边权的最大值,再枚举其中一个儿子 \(v\) 内有 \(k\) 个点为黑色。就能得到转移方程:

\[f_{u,j}=\max\{f_{u,j-k}+f_{v,k}+dis\times [k(m-k)+(siz_v-k)(n-siz_v-m+k)]\} \]

注意枚举 \(j\) 时要从大到小枚举,其原理类似于背包。

时间复杂度:\(O(n^2)\)

code
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int n,m;
int head[N],cnt;
int siz[N];
long long f[N][N];
struct Node
{
    int to,nxt,dis;
}e[N*2];
void add(int u,int v,int w)
{
    e[++cnt].to=v;
    e[cnt].dis=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa)
{
    siz[u]=1;
    f[u][0]=f[u][1]=0;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v==fa) continue;
        dfs(v,u);
        siz[u]+=siz[v];
        for(int j=min(siz[u],m);j>=0;j--)
        {
            for(int k=0;k<=min(siz[v],j);k++)
            {
                if(f[u][j-k]==-1) continue;
                f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]+1ll*e[i].dis*(k*(m-k)+(siz[v]-k)*(n-siz[v]-m+k)));
            }
        }
    }
}
int main()
{
    memset(f,-1,sizeof(f));
    cin>>n>>m;
    for(int i=1;i<=n-1;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,w);
    }
    dfs(1,0);
    cout<<f[1][m]<<endl;
    return 0;
}

C.光

正解

code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,k;
int sx,sy,sdir,cnt,cnt2,flag;
char s[5];
struct Point
{
    int x,y;
}a[N*4];
long long ans;
bool cmp(Point a,Point b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
vector<Point> d1[N*2],d2[N*2];
map<pair<int,int>,int> t1,t2;
void dfs(int x,int y,int dir)
{
    if(x==sx&&y==sy&&dir==sdir&&flag==1)
    {
        flag=2;
        return;
    }
    flag=1;
    if(dir==0)
    {
        if(t1[make_pair(x-1,y)]!=0&&t1[make_pair(x,y+1)]!=0) return;
        if(t1[make_pair(x-1,y)]==0&&t1[make_pair(x,y+1)]==0) return;
        if(t1[make_pair(x-1,y)]!=0) y++,dir=1;
        else x--,dir=2;
    }
    else if(dir==1)
    {
        if(t1[make_pair(x-1,y)]!=0&&t1[make_pair(x,y-1)]!=0) return;
        if(t1[make_pair(x-1,y)]==0&&t1[make_pair(x,y-1)]==0) return;
        if(t1[make_pair(x-1,y)]!=0) y--,dir=0;
        else x--,dir=3;
    }
    else if(dir==2)
    {
        if(t1[make_pair(x+1,y)]!=0&&t1[make_pair(x,y+1)]!=0) return;
        if(t1[make_pair(x+1,y)]==0&&t1[make_pair(x,y+1)]==0) return;
        if(t1[make_pair(x+1,y)]!=0) y++,dir=3;
        else x++,dir=0;
    }
    else
    {
        if(t1[make_pair(x+1,y)]!=0&&t1[make_pair(x,y-1)]!=0) return;
        if(t1[make_pair(x+1,y)]==0&&t1[make_pair(x,y-1)]==0) return;
        if(t1[make_pair(x+1,y)]!=0) y--,dir=2;
        else x++,dir=1;
    }
    if(dir==0) ans+=(long long)d2[x+y][t2[make_pair(x-1,y+1)]].x-x,dfs(d2[x+y][t2[make_pair(x-1,y+1)]].x,d2[x+y][t2[make_pair(x-1,y+1)]].y,dir);
    else if(dir==1) ans+=(long long)d1[x-y+m+1][t1[make_pair(x-1,y-1)]].x-x,dfs(d1[x-y+m+1][t1[make_pair(x-1,y-1)]].x,d1[x-y+m+1][t1[make_pair(x-1,y-1)]].y,dir);
    else if(dir==2) ans+=(long long)x-d1[x-y+m+1][t1[make_pair(x+1,y+1)]-2].x,dfs(d1[x-y+m+1][t1[make_pair(x+1,y+1)]-2].x,d1[x-y+m+1][t1[make_pair(x+1,y+1)]-2].y,dir);
    else ans+=(long long)x-d2[x+y][t2[make_pair(x+1,y-1)]-2].x,dfs(d2[x+y][t2[make_pair(x+1,y-1)]-2].x,d2[x+y][t2[make_pair(x+1,y-1)]-2].y,dir);
    return;
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++) cin>>a[i].x>>a[i].y;
    int dir=0;
    cin>>sx>>sy>>(s+1);
    if(s[1]=='N') dir+=2;
    if(s[2]=='E') dir+=1;
    for(int i=0;i<=n+1;i++)
    {
        a[++k].x=i,a[k].y=0;
        a[++k].x=i,a[k].y=m+1;
    }
    for(int i=1;i<=m;i++)
    {
        a[++k].x=0,a[k].y=i;
        a[++k].x=n+1,a[k].y=i;
    }
    sort(a+1,a+k+1,cmp);
    for(int i=1;i<=k;i++)
    {
        d1[a[i].x-a[i].y+m+1].push_back(a[i]);
        d2[a[i].x+a[i].y].push_back(a[i]);
        t1[make_pair(a[i].x,a[i].y)]=d1[a[i].x-a[i].y+m+1].size();
        t2[make_pair(a[i].x,a[i].y)]=d2[a[i].x+a[i].y].size();
        //cout<<a[i].x<<" "<<a[i].y<<endl;
        if(cnt) continue;
        if(dir==1&&sx-sy==a[i].x-a[i].y&&a[i].x>=sx) cnt=t1[make_pair(a[i].x,a[i].y)];
        if(dir==2&&sx-sy==a[i].x-a[i].y&&a[i].x>=sx) cnt=t1[make_pair(a[i].x,a[i].y)]-1;
        if(dir==3&&sx+sy==a[i].x+a[i].y&&a[i].x>=sx) cnt=t2[make_pair(a[i].x,a[i].y)]-1;
        if(dir==0&&sx+sy==a[i].x+a[i].y&&a[i].x>=sx) cnt=t2[make_pair(a[i].x,a[i].y)];
        if(cnt2) continue;
        if(dir==2&&sx-sy==a[i].x-a[i].y&&a[i].x>=sx) cnt2=t1[make_pair(a[i].x,a[i].y)];
        if(dir==1&&sx-sy==a[i].x-a[i].y&&a[i].x>=sx) cnt2=t1[make_pair(a[i].x,a[i].y)]-1;
        if(dir==0&&sx+sy==a[i].x+a[i].y&&a[i].x>=sx) cnt2=t2[make_pair(a[i].x,a[i].y)]-1;
        if(dir==3&&sx+sy==a[i].x+a[i].y&&a[i].x>=sx) cnt2=t2[make_pair(a[i].x,a[i].y)];
    }
    cnt--,cnt2--;
    int tx,ty;
    if(dir==1||dir==2) tx=d1[sx-sy+m+1][cnt].x,ty=d1[sx-sy+m+1][cnt].y;
    else tx=d2[sx+sy][cnt].x,ty=d2[sx+sy][cnt].y;
    sx=tx,sy=ty,sdir=dir;
    dfs(sx,sy,dir);
    //cout<<endl;
    if(flag==1)
    {
        if(dir==1||dir==2) tx=d1[sx-sy+m+1][cnt2].x,ty=d1[sx-sy+m+1][cnt2].y;
        else tx=d2[sx+sy][cnt2].x,ty=d2[sx+sy][cnt2].y;
        ans+=(long long)abs(tx-sx)-1;
        sx=tx,sy=ty,sdir=3-dir;
        flag=0,dfs(sx,sy,3-dir);
    }
    cout<<ans<<endl;
    return 0;
}

D.无向图问题

正解

标签:int,染色,make,t1,无向,五一,&&,pair,dir
来源: https://www.cnblogs.com/SpadeA261/p/16214768.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有