2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest G. Orientation of Edges

G. Orientation of Edges
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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:

to orient each undirected edge in one of two possible directions to maximize number of vertices reachable from vertex s;
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.

Examples
input
2 2 1
1 1 2
2 2 1
output

2

2
+
input
6 6 3
2 2 6
1 4 5
2 3 4
1 4 1
1 3 1
2 2 3
output
6
++-
2
+-+

链接:http://codeforces.com/contest/883/problem/G

题意:给一个由无向边和有向边组成的图,给定一个起点,问当你把无向边改变成有向边后,最大能到达多少个点,最少能到达多少个点,输出点的个数,并输出修改的第i条无向边的方向。

思路:
首先建图,用val表示该边是否有向,如果无向,用2表示正向,用3表示反向。
然后按照最优dfs走一遍,遇到有向边直接往下dfs,遇见无向边先记录方向,然后往下dfs。
再按照最劣dfs走一遍,遇到有向边往下dfs,遇见无向边记录反方向。

#include <bits/stdc++.h>
using namespace std;
#define maxn 300005

struct node
{
    int to,val,id;
    node(int to,int val):to(to),val(val){}
    node(int to,int val,int id):to(to),val(val),id(id){}
};
int cnt=0;
vector<node> g[maxn];

int ans1[maxn],ans2[maxn];
bool vis[maxn];

void dfs1(int s)
{
    vis[s]=1;
    for(auto v:g[s])
    {
        if(vis[v.to])continue;
        if(v.val==1)
        {
            ans1[0]++;
            dfs1(v.to);
        }
        else if(v.val==2)
        {
            ans1[0]++;
            ans1[v.id]=1;
            dfs1(v.to);
        }
        else
        {
            ans1[0]++;
            ans1[v.id]=0;
            dfs1(v.to);
        }
    }
}

void dfs2(int s)
{
    vis[s]=1;
    for(auto v:g[s])
    {
        if(vis[v.to])continue;
        if(v.val==1)
        {
            ans2[0]++;
            dfs2(v.to);
        }
        else if(v.val==2)
            ans2[v.id]=0;
        else
            ans2[v.id]=1;
    }
}

int main()
{
    int n,m,s,t,u,v;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&t,&u,&v);
        if(t==1)
        {
            g[u].push_back(node(v,1));
        }
        else
        {
            g[u].push_back(node(v,2,++cnt));//2表示正向
            g[v].push_back(node(u,3,cnt));//3表示反向
        }
    }
    dfs1(s);

    printf("%d\n",ans1[0]+1);
    for(int i=1;i<=cnt;i++)
    {
        printf("%c",(ans1[i])?'+':'-');
    }printf("\n");

    memset(vis,0,sizeof(vis));
    dfs2(s);

    printf("%d\n",ans2[0]+1);
    for(int i=1;i<=cnt;i++)
    {
        printf("%c",(ans2[i])?'+':'-');
    }printf("\n");

    return 0;
}

转载请注明出处^ ^

猜你喜欢

转载自blog.csdn.net/mmingfunnytree/article/details/78306723