缩点+树上差分——Codeforces555E Case of Computer Network

题面:cf555e
简要题意:给出一个无向图,给出q个询问S,T表示从S走到T。问能否给这张图的边定向,使得满足q个询问


我们首先发现对于每一个边双连通分量,两两之间是可以随便到达的,包括去到外面的点。所以我们把边双都缩成一个点,这张图就变成了一棵树
对于树进行操作就简单多了,我们只要在S,T,LCA位置打上差分标记(S打向上,T打向下,LCA打消除),然后一遍dfs从下往上扫一遍,如果某个节点向下向上标记都存在的话,这条边就发生冲突了

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
using namespace std;
inline int read(){
    int k=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}
    return k*f;
}
int nedge=0,p[400010],nex[400010],head[400010];
int nedge1=0,p1[400010],nex1[400010],head1[400010];
int dfn[200010],low[200010],s[200010],d[200010],l[200010];
int n,m,q,cnt=0,Top=0,vis[200010];
int deep[200010],f[200010],son[200010],top[200010];
int fa[200010],rp[200010][2],b[200010];
inline int getfather(int x){return fa[x]==x?x:fa[x]=getfather(fa[x]);}
inline void addedge(int a,int b){
    p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;
}
inline void addedge1(int a,int b){
    p1[++nedge1]=b;nex1[nedge1]=head1[a];head1[a]=nedge1;
}
inline void tarjan(int x,int fa){
    dfn[x]=low[x]=++cnt;
    s[++Top]=x;bool r=1;b[x]=1;
    for(int k=head[x];k;k=nex[k]){
        if(p[k]==fa&&r){
            r=0;continue;
        }
        if(!dfn[p[k]])tarjan(p[k],x),low[x]=min(low[x],low[p[k]]);
        else if(b[p[k]])low[x]=min(low[x],dfn[p[k]]);
    }
    if(dfn[x]==low[x]){
        d[0]++;int k=0;
        do{
            k=s[Top--];d[d[0]]++;l[k]=d[0];b[k]=0;
        }while(k!=x);
    }
}
inline void dfs(int x,int fat,int dep){
    vis[x]=1;
    deep[x]=dep;s[x]=1;f[x]=fat;
    for(int k=head1[x];k;k=nex1[k])if(p1[k]!=fat){
        dfs(p1[k],x,dep+1);s[x]+=s[p1[k]];
        if(s[p1[k]]>s[son[x]])son[x]=p1[k];
    }
}
inline void dfss(int x,int t){
    top[x]=t;
    if(son[x])dfss(son[x],t);
    for(int k=head1[x];k;k=nex1[k])if(p1[k]!=f[x]&&p1[k]!=son[x])dfss(p1[k],p1[k]);
}
inline int lca(int x,int y){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
        x=f[fx];fx=top[x];
    }
    if(deep[x]>deep[y])swap(x,y);return x;
}
inline void DFS(int x){
    vis[x]=2;
    for(int k=head1[x];k;k=nex1[k]){
        int to=p1[k];
        if(to==f[x])continue;
        DFS(to);rp[x][0]+=rp[to][0];rp[x][1]+=rp[to][1];
    }
    if(rp[x][0]*rp[x][1]){puts("No");exit(0);}
}
int main()
{
    n=read();m=read();q=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        addedge(x,y);addedge(y,x);
    }
    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
    for(int i=1;i<=d[0];i++)fa[i]=i;
    for(int i=1;i<=n;i++)
        for(int k=head[i];k;k=nex[k])if(l[i]!=l[p[k]]){
            addedge1(l[i],l[p[k]]);
            int fx=getfather(l[i]),fy=getfather(l[p[k]]);
            fa[fx]=fy;
        }
    n=d[0];
    for(int i=1;i<=n;i++)if(!vis[i]){
        dfs(i,0,1);dfss(i,i);
    }
    for(int i=1;i<=q;i++){
        int x=l[read()],y=l[read()];
        int fx=getfather(x),fy=getfather(y);
        if(fx!=fy)return puts("No")&0;
        int LCA=lca(x,y);
        rp[x][0]++;rp[y][1]++;rp[LCA][0]--;rp[LCA][1]--;
    }
    for(int i=1;i<=n;i++)if(vis[i]!=2)DFS(i);
    puts("Yes");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用的内容,CodeForces的初始分由1500改为了1400,并且前六场的初始分配如下:第一场500分,第二场350分,第三场250分,第四场150分,第五场100分,第六场50分。所以,根据你在第一场的表现分为368,你的总分应为868(1400+368)。接下来的五场比赛,你的表现分将根据具体情况来决定。每场比赛的表现分会对你的总分产生影响。 关于其他引用和的代码,它们似乎是一些针对不同情况进行计算和输出的算法,并不直接涉及到CodeForces上的分数计算。所以,如果你有关于CodeForces上分的具体问题,请提供更多详细信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [CodeForces前六场定级赛赋分规则(2020.5修订)及各段位对应分数段](https://blog.csdn.net/Sunshine_xiaohao/article/details/112106625)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [CodeForces上分日记 (思维题)(A. Garland)1809A (Educational Round 145 For Div.2)](https://blog.csdn.net/weixin_60375636/article/details/130243342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【codeforces】一切为了上分:骚操作合集](https://blog.csdn.net/weixin_45497996/article/details/109157711)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值