LOJ#6581. 「ICPC World Finals 2019」断头路探测者

Description

你家乡的议会决定对一些道路标志的安置进行改进,特别是一些断头路。他们给了你一个地图,你必须确定在哪里贴上「此路不通」标志,他们希望你使用的标志尽可能少。

sign.png

地图是由双向街道连接一些地点而形成的集合。以下规则描述了在一个街道 $S$的入口 $x$安放一个「此路不通」标志的条件:如果在从 $x$点进入街道 $S$后,只能通过掉头的方式回到$x$,就应该安装一个「此路不通」标志。定义一个「掉头」操作为做一个 $180$度的转弯,即立刻反转行车的方向。

为了节省成本,你决定不安装任何多余的标志。如果一个街道 $S$的入口$x$ 有一个「此路不通」标志,另一条街道$T$ 的入口$y$ 有一个「此路不通」标志,如果从$x$ 点进入街道 $S$,并能在不掉头的情况下经过 $y$点进入街道$T$ ,那么 $T$的入口 $y$处的标志就是多余的。

Solution

对于有环的连通块,符合要求的边不指向环的边

对于无环的连通块,符合要求的边为叶子边

拓扑排序即可

#include<algorithm>
#include<iostream>
#include<utility>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
using namespace std;
int n,m,du[500005],tot;
bool vst[500005];
vector<int>G[500005];
queue<int>q;
pair<int,int>ans[500005];
inline int read()
{
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
int main()
{
    n=read();
    m=read();
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read();
        G[u].push_back(v);
        G[v].push_back(u);
        ++du[u];
        ++du[v];
    }
    for(int i=1;i<=n;i++)
    {
        if(du[i]==1)
        {
            q.push(i);
            vst[i]=true;
        }
    }
    while(q.size())
    {
        int u=q.front();
        q.pop();
        for(auto v:G[u])
        {
            if(!vst[v]&&--du[v]==1)
            {
                vst[v]=true;
                q.push(v);
            }
        }
    }
    memset(vst,false,sizeof(vst));
    for(int i=1;i<=n;i++)
    {
        if(du[i]>=2)
        {
            q.push(i);
            vst[i]=true;
        }
    }
    while(q.size())
    {
        int u=q.front();
        q.pop();
        for(auto v:G[u])
        {
            if(!vst[v]&&du[v]==1)
            {
                vst[v]=true;
                q.push(v);
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(auto v:G[i])
        {
            if(vst[i]&&du[i]>1&&du[v]==1)
            {
                ans[++tot]=make_pair(i,v);
            }
            if(!vst[i]&&G[i].size()==1)
            {
                ans[++tot]=make_pair(i,v);
            }
        }
    }
    sort(ans+1,ans+tot+1);
    printf("%lld\n",tot);
    for(int i=1;i<=tot;i++)
    {
        printf("%lld %lld\n",ans[i].first,ans[i].second);
    }
    return 0;
}
「ICPC World Finals 2019」断头路探测者

 

posted @ 2020-10-27 20:52  QDK_Storm  阅读(281)  评论(0编辑  收藏  举报