CF Round #550 (Div. 3) F Graph Without Long Directed Paths

题目链接:

http://codeforces.com/contest/1144/problem/F

题意:

给你一个n个节点m条边( u u u i i i, v v v j j j)的无向图,让你给每条边指定方向,使得得到的有向图,任意两点之间如果可达,那么距离不超过2(意思是,任意两点要么不可达,要么只有一条有向边连接这两个点),问是否能得到这样的有向图,能输出’'YES",否则输出"NO";如果能得到这样的图,然后对于每个输入的边( u u u i i i, v v v j j j)(无向),如果你给它指定的方向与输入时的方向相同那么,标记个1,否则标记个0,最后你就会得到一个01串,输出01(多个结果输出任意一个);

分析:

简单题;很容易发现,如果某个点(第一类)的边都发散出去,即从它自己指向其他点(第二类),那么它指向的每个点(第二类)连接的所有边一定是指向这些点(第二类)本身的,然后这些点连接的点的边一定是发散的即指向其他点的;简单的说,如果第一个点的边是发散的,那么与它距离为奇数的点的边也一定是发散的,距离为偶数的点的边一定是汇聚的,那么存在这样的情况,某两个点之间有边相连,且他们到开始第一个点的距离同奇或者同偶,那么就会出现尴尬的局面,这样就是"NO"的情况;
所以剩下就是dfs或bfs搜索的事情了;

代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;

const int inf=0x7f7f7f7f;
const int maxn=1e1+50;
const int N=2e5+50;
typedef long long ll;
typedef struct{
    ll u,v,next,w;
}Edge;
Edge e[2*N];
int cnt,head[N];

inline void add(int u,int v){
    e[cnt].u=u;
    e[cnt].v=v;
    //e[cnt].w=w;
    // e[cnt].f=f;
    e[cnt].next=head[u];
    head[u]=cnt++;
    e[cnt].u=v;
    e[cnt].v=u;
    // e[cnt].w=0;
    // e[cnt].f=-f;
    e[cnt].next=head[v];
    head[v]=cnt++;
}
inline void write(int x)
{
     if(x<0) 
        putchar('-'),x=-x;
     if(x>9)
        write(x/10);
     putchar(x%10+'0');
}

inline int read()
{
    int x = 0;
    int f = 1;
    char c = getchar();
    while (c<'0' || c>'9'){    
        if (c == '-')
            f = -1;
        c = getchar();
    }
    while (c >= '0'&&c <= '9'){
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x*f;
}


int u,v,n,m,level[N];

void bfs(int x){
    level[x]=1;
    queue<int >q;
    q.push(x);
    while(!q.empty()){
        int t=q.front();q.pop();
        for(int i=head[t];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(!level[v]){
                q.push(v);
                level[v]=level[t]+1;
            }
        }
    }
}
int main() {
    queue<pair<int ,int > >q;
    cin>>n>>m;
    memset(head,-1,sizeof(head));
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        q.push({u,v});
        add(u,v);
    }
    bfs(1);
    string res="";
    while(!q.empty()){
        int fi=q.front().first,se=q.front().second;q.pop();
        if(level[fi]%2==level[se]%2){
            cout<<"NO"<<endl;
            return 0;
        }
        if(level[fi]%2)res+='1';
        else res+='0';
    }
    cout<<"YES"<<endl;
    cout<<res<<endl;
    return 0;
}

(仅供个人理解)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值