cf883 G. Orientation of Edges(贪心)

题意:

图中有有向边和无向边,可能有重边。现要把原图中的无向边全变成有向边,构造两个图:第一个图最大化从s点出发能到达的点数,第二个图最小化从s点出发能到达的点数

思路:

dfs,遇到有向边就直接走,遇到无向边时:

若要取max就把边的方向置为 u->v,并继续走;

若要取min就把边的方向置为 v<-u,注意接下来不能走到v。

const int N = 3e5 + 5;
int n, m, s;
vector<PII> G[N]; //to,id(id=0有向边,>0无向边)
int vis[N], start[N], ans, opp[N], idx;
//idx无向边数,opp某条边是否要反向,start某无向边原来的起点
bool ismin;
void dfs(int u)
{
    ans++, vis[u] = 1;
    for(auto [v, id] : G[u])
    {
        if(vis[v]) continue;
        if(!id) dfs(v); //有向边,继续走
        else if(ismin) opp[id] = (start[id] != v); //无向边,看要不要反向
        else opp[id] = (start[id] != u), dfs(v);
    }
}

signed main()
{
    iofast;
    cin >> n >> m >> s;
    for(int i = 1; i <= m; i++)
    {
        int t, u, v; cin >> t >> u >> v;
        if(t == 1) G[u].pb({v,0});
        else start[++idx] = u, G[u].pb({v,idx}), G[v].pb({u,idx});
    }

    dfs(s);
    //输出答案
    cout << ans << endl;
    for(int i = 1; i <= idx; i++) cout << (opp[i]?'-':'+');
    cout << endl;
    //init
    memset(opp, 0, sizeof opp);
    memset(vis, 0, sizeof vis);
    ans = 0, ismin = 1;

    dfs(s);
    //输出答案
    cout << ans << endl;
    for(int i = 1; i <= idx; i++) cout << (opp[i]?'-':'+');
}

上一篇:acwing 843. n-皇后问题


下一篇:ansible 自动化运维工具 9 (ansible角色的安装及使用)