Codeforces 883G Orientation of Edges(BFS+MAP)

原题链接

Problem Description

Vasya has a graph containing both directed (oriented) and undirected (non-oriented) edges. There can be multiple edges between a pair of vertices.

Vasya has picked a vertex s from the graph. Now Vasya wants to create two separate plans:

  1. to orient each undirected edge in one of two possible directions to maximize number of vertices reachable from vertex s;
  2. to orient each undirected edge in one of two possible directions to minimize number of vertices reachable from vertex s.
    In each of two plans each undirected edge must become directed. For an edge chosen directions can differ in two plans.

Help Vasya find the plans.

Input

The first line contains three integers n, m and s (2 ≤ n ≤ 3·105, 1 ≤ m ≤ 3·105, 1 ≤ s ≤ n) — number of vertices and edges in the graph, and the vertex Vasya has picked.

The following m lines contain information about the graph edges. Each line contains three integers ti, ui and vi (1 ≤ ti ≤ 2, 1 ≤ ui, vi ≤ n, ui ≠ vi) — edge type and vertices connected by the edge. If ti = 1 then the edge is directed and goes from the vertex ui to the vertex vi. If ti = 2 then the edge is undirected and it connects the vertices ui and vi.

It is guaranteed that there is at least one undirected edge in the graph.

Output

The first two lines should describe the plan which maximizes the number of reachable vertices. The lines three and four should describe the plan which minimizes the number of reachable vertices.

A description of each plan should start with a line containing the number of reachable vertices. The second line of a plan should consist of f symbols ‘+’ and ‘-‘, where f is the number of undirected edges in the initial graph. Print ‘+’ as the j-th symbol of the string if the j-th undirected edge (u, v) from the input should be oriented from u to v. Print ‘-’ to signify the opposite direction (from v to u). Consider undirected edges to be numbered in the same order they are given in the input.

If there are multiple solutions, print any of them.

Sample Input

6 6 3
2 2 6
1 4 5
2 3 4
1 4 1
1 3 1
2 2 3

Sample Output

6
++-
2
+-+

题目大意

给一张图,其中的边有些是单向边有些是双向边,这里的双向边的含义是边的方向暂未给定。现给定一个起点,问如何安排这些双向边的方向,使得从这个点出发可以到达的点最多,如何到达的点最少。

解题思路

从起点开始BFS,遇到单向边只能向前走。若要使到达的点的数目最多,遇到双向边时要让边的箭头指向外部,反之指向内部。比赛的时候一直WA是因为没有考虑清楚重边的情况,MAP在映射不同的重边时总是指向了同一条边。

AC代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
#include<list>
#include<stack>
#include<set>
#include<map>
#define ll long long
#define ull unsigned long long
#define db double
#define rep(i,n) for(int i = 0;i < n; i++)
//#define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++)
//#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define pb push_back
#define mp make_pair
#define exp 2.7182818
#define PI 3.141592653589793238462643383279502884
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define eps 1e-8
#define MOD 1000000007ll
using namespace std;

struct ssign
{
    int id;
    int from;
    int to;
    ssign(){}
    ssign(int _id,int _from,int _to)
    {
        id=_id;
        from=_from;
        to=_to;
    }
    bool operator<(const ssign &oth) const
    {
        return id<oth.id;
    }
};


int n,m,s;
map<ssign,int> mmp;
struct in
{
    int id;
    int to;
    int type;
    in(){}
    in(int _id,int _to,int _type)
    {
        id=_id;
        to=_to;
        type=_type;
    }
};
struct node
{
    //int id;
    int from;
    int to;
    int res=-1;
}unk[300010];
vector<in> mat[300010];
int vis[300010];
int main(void) 
{
    //freopen("input.in","r",stdin);
    //freopen("output.out","w",stdout);
    cl(vis);
    cin>>n>>m>>s;
    int op,from,to;
    int type;
    int numoftwo=1;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&type,&from,&to);
        if(type==1)
        {
            mat[from].pb(in(i,to,1));
        }
        else
        {
            mat[from].pb(in(i,to,2));
            mat[to].pb(in(i,from,2));
            mmp[ssign(i,from,to)]=numoftwo;
            mmp[ssign(i,to,from)]=numoftwo;
            unk[numoftwo].from=from;
            unk[numoftwo].to=to;
            numoftwo++;
        }
    }

    int res=1;
    vis[s]=1;
    queue<int> qq;
    qq.push(s);
    while(!qq.empty())
    {
        int out=qq.front();
        qq.pop();
        for(int i=0;i<mat[out].size();++i)
        {
            if(!vis[mat[out][i].to])
            {
                vis[mat[out][i].to]=1;
                if(mat[out][i].type==1)
                {
                    qq.push(mat[out][i].to);
                    res++;
                }
                else
                {
                    int get=mmp[ssign(mat[out][i].id,out,mat[out][i].to)];
                    if(unk[get].from==out)
                    {
                        unk[get].res=1;
                        qq.push(mat[out][i].to);
                        res++;
                    }
                    else
                    {
                        unk[get].res=0;
                        qq.push(mat[out][i].to);
                        res++;
                    }
                }
            }

        }
    }
    cout<<res<<endl;
    for(int i=1;i<=numoftwo-1;++i)
    {
        if(unk[i].res==0)
        {
            printf("-");
        }
        else 
        {
            printf("+");
        }
    }
    cout<<endl;

    for(int i=0;i<=300005;++i)
    {
        unk[i].res=-1;
    }

    cl(vis);
    res=1;
    vis[s]=1;
    while(!qq.empty()) qq.pop();
    qq.push(s);
    while(!qq.empty())
    {
        int out=qq.front();
        qq.pop();
        for(int i=0;i<mat[out].size();++i)
        {
            if(!vis[mat[out][i].to])
            {

                if(mat[out][i].type==1)
                {
                    vis[mat[out][i].to]=1;
                    qq.push(mat[out][i].to);
                    res++;
                }
                else
                {
                    int get=mmp[ssign(mat[out][i].id,out,mat[out][i].to)];
                    if(unk[get].from==out)
                    {
                        unk[get].res=0;
                        //qq.push(mat[out][i].to);
                        //res++;
                    }
                    else
                    {
                        unk[get].res=1;
                        //qq.push(mat[out][i].to);
                        //res++;
                    }
                }
            }

        }
    }



    cout<<res<<endl;
    for(int i=1;i<=numoftwo-1;++i)
    {
        if(unk[i].res==0)
        {
            printf("-");
        }
        else 
        {
            printf("+");
        }
    }
    cout<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值