首页 > 其他分享 >cd graph

cd graph

时间:2024-01-30 15:35:34浏览次数:19  
标签:ch int graph cd ++ times id getchar

图论专场

Fairy(CF19E)

题目大意

给出一张无向图,求删除一条边后此图变成二分图的所有删边种类 \((n\leq10^4)\)。

思路

虽然看起来 \(O(n^2)\) 能过,但其实是过不了的,我们知道,判断二分图的一种方式是判断有无奇环,所以问题变成了删去一条边后图中有无奇环,如果有环重合,可以用类似异或的逻辑将中间重复的取消,在看成一个环,明显发现只有偶环+奇环=奇环,然后就做完了。

#include<bits/stdc++.h>
#define ll long long
#define mm 10010
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
struct node{
    int nxt,v,id;
}e[mm<<2];
int head[mm<<2],tot=1,dfn[mm];
int n,m,ans[mm],p[mm],f[mm],Ans;
int c1[mm],c2[mm],cnt;
void ADD(int x,int y,int id)
{
    e[++tot]=(node){head[x],y,id};
    head[x]=tot;
}
void dfs(int x,int fa,int pre)
{
    dfn[x]=dfn[fa]+1;
    p[x]=e[pre].id;
    for(int i=head[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
    {
        if((i^pre)==1)
            continue;
        if(!dfn[v])
        {
            dfs(v,x,i);
            f[e[i].id]=1;
            c1[e[pre].id]+=c1[e[i].id];
            c2[e[pre].id]+=c2[e[i].id];
        }
        else
        {
            if(x==v && i&1)
                ++c1[e[i].id],++cnt;
            else
            {
                if(dfn[x]>dfn[v])
                if((dfn[x]-dfn[v])&1)
                {
                    ++c2[e[i].id];
                    ++c2[e[pre].id];
                    --c2[p[v]];
                }
                else
                {
                    ++c1[e[i].id];
                    ++c1[e[pre].id];
                    --c1[p[v]];
                    ++cnt;
                }
            }
        }
    }
}
void print()
{
    printf("%d\n",Ans);
    for(int i=1;i<=Ans;i++)
        printf("%d ",ans[i]);
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        ADD(x,y,i);
        ADD(y,x,i);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i,0,0);
    if(!cnt)
    {
        for(int i=1;i<=m;i++)
            ans[++Ans]=i;
        print();
        return 0;
    }
    for(int i=1;i<=m;i++)
        if(f[i])
        {
            if(c1[i]==cnt && !c2[i])
                ans[++Ans]=i;
        }
        else
        {
            if(cnt==1 && c1[i]==1)
                ans[++Ans]=i;
        }
    print();
    return 0;
}

Connecting Cities(AT_keyence2019_e)

题目大意

给定 \(N\) 个点的完全图图,每个点有权值 \(A_i\)。对于任何点 \(i\) 和点 \(j\),这两点之间的边权为 \(w_{i,j} = A_i + A_j + D|i - j|\),其中 \(D\) 为给定的常数,求最小生成树的大小。\((N\leq 2\times 10^5,A_i,D\leq 10^9)\)

思路

还是用 \(prim\) 或 \(Kruskal\),但这题不可以全部连边,可以发现有些边是不必要的,先考虑把式子简化,我们如果确定这两个 \(i\) 和 \(j\),可以变成 \(A_i+D\times i+A_j-D\times j\)。

既然 \(i\) 和 \(j\) 独立出来,那么只需要选出,右半部分 \(min{A_i+D\times i}\) 所对应的 \(i\),左半部分 \(min{A_j+D\times j}\) 所对应的 \(j\),将 \(j\) 与右半部分所有点连边,\(i\) 同理,这样边就只有 \(O(nlog_n)\),最后跑 \(Kruskal\)。

#include<bits/stdc++.h>
#define ll long long
#define mm 10010
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
struct node{
    int nxt,v,id;
}e[mm<<2];
int head[mm<<2],tot=1,dfn[mm];
int n,m,ans[mm],p[mm],f[mm],Ans;
int c1[mm],c2[mm],cnt;
void ADD(int x,int y,int id)
{
    e[++tot]=(node){head[x],y,id};
    head[x]=tot;
}
void dfs(int x,int fa,int pre)
{
    dfn[x]=dfn[fa]+1;
    p[x]=e[pre].id;
    for(int i=head[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
    {
        if((i^pre)==1)
            continue;
        if(!dfn[v])
        {
            dfs(v,x,i);
            f[e[i].id]=1;
            c1[e[pre].id]+=c1[e[i].id];
            c2[e[pre].id]+=c2[e[i].id];
        }
        else
        {
            if(x==v && i&1)
                ++c1[e[i].id],++cnt;
            else
            {
                if(dfn[x]>dfn[v])
                if((dfn[x]-dfn[v])&1)
                {
                    ++c2[e[i].id];
                    ++c2[e[pre].id];
                    --c2[p[v]];
                }
                else
                {
                    ++c1[e[i].id];
                    ++c1[e[pre].id];
                    --c1[p[v]];
                    ++cnt;
                }
            }
        }
    }
}
void print()
{
    printf("%d\n",Ans);
    for(int i=1;i<=Ans;i++)
        printf("%d ",ans[i]);
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        ADD(x,y,i);
        ADD(y,x,i);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i,0,0);
    if(!cnt)
    {
        for(int i=1;i<=m;i++)
            ans[++Ans]=i;
        print();
        return 0;
    }
    for(int i=1;i<=m;i++)
        if(f[i])
        {
            if(c1[i]==cnt && !c2[i])
                ans[++Ans]=i;
        }
        else
        {
            if(cnt==1 && c1[i]==1)
                ans[++Ans]=i;
        }
    print();
    return 0;
}

Tournament(CF878C)

题目大意

有 \(n\) 个人,每个人都有 \(k\) 种能力值 \(a_{i,1},a_{i,2}……a_{i,k}\)。

定义淘汰赛的规则如下:在没被淘汰的人中选出两个 \(i\) 和 \(j\),并选择 \(d\in [1,k]\)。如果 \(a_{i,d} > a_{j,d}\),则 \(j\) 淘汰;否则 \(i\) 淘汰(保证所有的 \(a_{i,d}\) 互不相同)。直到只剩下一个人没有被淘汰,则这个人是最终的胜者。

对于每个 \(i\),需要求出如果初始参加比赛的人是 \(1,2,...,i\),这 \(i\) 个人里有多少人可能成为最终的胜者。

\(n\leq 5\times 10^4,k\leq 10\)

思路

我们考虑两个选手之间的关系,如果一个选手能在某一项运动中战胜对手,那么就从他自身向对手连一条有向边。这样显然会出现很多环,于是可以缩点,将整张图缩成一条链。那么显然入度为零的环中包含的点数即为最后可能成为冠军的人数。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int n,k;
struct node{
    int siz;
    int maxn[15],minn[15];
    node(){
        memset(maxn,0,sizeof(maxn));
        memset(minn,0x3f,sizeof(minn));
    }
    friend bool operator <(node a,node b){
        for(int i=1;i<=k;i++)
            if(a.maxn[i]>b.minn[i])
                    return false;
        return true;
    }
};
set<node> s;
set<node>::iterator it;
int main()
{
    n=read(),k=read();
    node t;
    for(int i=1;i<=n;i++)
    {
        t.siz=1;
        for(int j=1;j<=k;j++)
            t.maxn[j]=t.minn[j]=read();
        while((it=s.find(t))!=s.end())
        {
            t.siz+=it->siz;
            for(int j=1;j<=k;j++)
            {
                t.minn[j]=min(t.minn[j],it->minn[j]);
                t.maxn[j]=max(t.maxn[j],it->maxn[j]);
            }
            s.erase(it);
        }
        s.insert(t);
        printf("%d\n",(--s.end())->siz);
    }
    return 0;
}

标签:ch,int,graph,cd,++,times,id,getchar
From: https://www.cnblogs.com/noipwen/p/17997219

相关文章

  • cd 数论
    数论专场StrangeLimit题目大意给你\(p\)和\(m\),求\(p^{p^{p^{p……}}}\mod\m!\)思路有\(n\)个\(p\),\(n\)为无穷大,也就是递归里套一个指数循环节,然后因为\(n\)趋向于无限大,那么当前要\(mod\)的\(x\)\(\mu(\mu(\mu(m)))\),也在一直缩小。如果当\(p\mo......
  • cd 游记
    Day1差不多晚上才到,去吃了火锅,菜里都有花椒,晚上在寝室整理自己的东西,了解了一下制度。Day2上午先做了一下昨天的题目,难度还行,补了\(Ice-creamTycoon\)和\(NewYearandConference\),下午是金天讲课,知道了许多有意思的DS转换,难度为单峰。中午和yjf和hhx去外面吃饭,吃的云吞,......
  • etcd v2 版本数据备份恢复脚本
    importrequestsimportjsonimportsysaction=sys.argv[1]etcdaddr=sys.argv[2]defbackup_data():url=f"{etcdaddr}/v2/keys/?recursive=true"response=requests.get(url)ifresponse.status_code==200:data=res......
  • Walrus 实用教程|Walrus + Gitlab,打通CI/CD 自动化交付!
    Walrusfile是Walrus0.5版本推出的新功能,用户可以通过一个非常简洁的YAML描述应用或基础设施资源的部署配置,然后通过WalrusCLI执行walrusapply或在WalrusUI上进行import,将Walrusfile提交给Walrusserver,由Walrusserver完成对应用或基础设施资源的部署/配置/......
  • 出大招了,这个顶级 CI/CD 产品,最近甩出了两个“王炸”
    极狐GitLabCI自16.0版本以来,陆续引入了CI/CDcomponent和CI/CDCatalog两个重量级功能,提高了CI/CD流水线的复用性,从此编写流水线可能像搭积木那样便捷了。计算机中的所有问题都可以通过增加一个间接层来解决。——DavidWheeler(大卫·惠勒)编写CI/CD流水线是DevO......
  • PCDN 流量盒子 系统定制 OEM看过来
    赋能每个家庭,闲置带宽流量可以变成收益的PCDN机顶盒,各位听说过吗?PCDN是一种高效的内容分发网络,它通过负载均衡、数据优化、网络优化等技术,提高网站的可用性、稳定性和性能。PCDNOEM,电话/微信:13540308877我们专注于使用自主可控的核心技术构建跨越“云-边-端”的全栈边缘计算,......
  • 深入理解 Flink(六)Flink Job 提交和 Flink Graph 详解
    FlinkProgram编程套路回顾1、获取执行环境对象StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();2、通过执行环境对象,注册数据源Source,得到数据抽象DataStreamds=env.socketTextStream(...)3、调用数据抽象的各种Transformation......
  • Gogs,支付宝沙箱支付,DevOps&CI/CD
    1.Gogs2.支付宝沙箱支付测试3.DevOps是生么4.CI/CD是什么1.Gogs是一款极易搭建的自助Git服务。Gogs的目标是打造一个最简单、最快速和最轻松的方式搭建自助Git服务。使用Go语言开发使得Gogs能够通过独立的二进制分发,并且支持Go语言支持的所有平台,包括Linux、Ma......
  • 第二届数字化经济与管理科学国际学术会议(CDEMS 2024)
    【经济&管理|录用率高】第二届数字化经济与管理科学国际学术会议(CDEMS2024)20242nd InternationalConferenceonDigitalEconomyandManagementScience(CDEMS2024) 重要信息 大会官网:www.icdems.com 大会时间:2024年4月26-28日大会地点:武汉(线上线下结合)✱截稿日期:20......
  • UOJ #33 树上 GCD
    套路地,对每个\(g\in[1,n-1]\)求出有多少对无序对\((u,v)\)满足\(g|f(u,v)\),然后就可以用一个倒序枚举的\(\mathcalO(n\logn)\)的容斥求出答案。考虑点分治,对每个经过分治中心\(c\)的\(u\rightsquigarrow\text{lca}(u,v)\rightsquigarrowv\)只需分两种......