E - E CodeForces - 1100E (+ half topological sort)

E - E CodeForces - 1100E

N has a directed graph nodes, the nodes are numbered from 1 to n, m the presence of unidirectional edges. Each edge has a weight-way, on behalf of the cost required for reversing the direction thereof. FIG seeking to make into acyclic graph, where the maximum edge flip smallest weighting schemes, and the maximum right side of the flip scheme.

Input single set of inputs, a first line contains two integers n and m (2≤n≤100 000,1≤m≤100 000) Next m lines of three integers, u_i, V_I
, W_i (. 1 <= u_i, V_I <= n-,. 1 <= W_i <=
10 ^. 9), there is a u to v represents a weight of w to the road. From the beginning of the road number 1. No loopback.

Output Output two integers in the first line, that is, to flip right side of the largest, and the need to reverse the number of road k. k need not be minimal.

On the next line output k-space separated integer representing the number of road need to flip the

If there are many solutions, print any of them.

Examples
Input
5 6
2 1 1
5 2 6
2 3 2
3 4 3
4 5 5
1 5 4
Output
2 2
1 3 
Input
5 7
2 1 5
3 2 3
1 3 3
2 4 1
4 3 5
5 4 1
1 5 3
Output
3 3
3 4 7 

Thinking

  • Meaning of the title: Give me a map to the weighted value, this figure may exist ring, while the minimum weight reversal ask how much is needed to change the whole?
  • Ideas: first with binary enumeration, the maximum side to the right side of the minimum inverting mid, are given a drawing of the right side edge of the edge is less than the mid considered bidirectional edge (not present), then the remaining FIG child under the running side topological sort, to see whether there ring, if any, so let l = mid + 1, otherwise r = mid - 1
  • link

answer

#include<iostream>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#define int long long
#define inf 10000000000000
using namespace std;
int read(){
    int res=0;char ch=0;
    while (!isdigit(ch))ch=getchar();
    while (isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}

const int N=1000100;
struct EDGE{
    int ver,nxt,dis,pre;
}edge[N];
int n,m,cnt,head[N],vis[N],d[N],ans[N],dfn[N],dfs_cnt;

void add(int u,int v,int t){
    edge[++cnt].ver=v;
    edge[cnt].nxt=head[u];
    edge[cnt].dis=t;
    edge[cnt].pre=u;
    head[u]=cnt;
}

queue<int>q;
bool check(int x){

    memset(d,0,sizeof(d));memset(vis,0,sizeof(vis));

    for (int i=1;i<=m;i++)if(edge[i].dis>x)d[edge[i].ver]++;

    for (int i=1;i<=n;i++)if (!d[i])q.push(i);

    while (!q.empty()){

        int u=q.front();q.pop();

        for (int i=head[u];i;i=edge[i].nxt)
        {
            if (edge[i].dis<=x)continue;

            int v=edge[i].ver;d[v]--;if (!d[v])q.push(v);
        }
    }

    for (int i=1;i<=n;i++)if (d[i])return 0;

    return 1;
}
void solute(int x){
    memset(d,0,sizeof(d));memset(vis,0,sizeof(vis));

    for (int i=1;i<=m;i++)if(edge[i].dis>x)d[edge[i].ver]++;
    for (int i=1;i<=n;i++)if (!d[i])q.push(i);

    while (!q.empty())
    {
        int u=q.front();q.pop();dfn[u]=++dfs_cnt;

        for (int i=head[u];i;i=edge[i].nxt)
        {
            if (edge[i].dis<=x)continue;
            int v=edge[i].ver;d[v]--;if (!d[v])q.push(v);
        }
    }

    for (int i=1;i<=m;i++){
        if (edge[i].dis<=x){
            int u=edge[i].pre,v = edge[i].ver;
            if (dfn[u]>dfn[v])ans[++cnt]=i;
        }
    }
}
signed main(){
    n=read();m=read();
    for (int i=1;i<=m;i++){
        int x=read(),y=read(),t=read();add(x,y,t);
    }
    int l=0,r=inf;
    while (l<r)
    {
        int mid=l+r>>1;
        if (check(mid))
            r=mid;
        else
            l=mid+1;
    }

    cnt=0;
    solute(r);
    printf("%lld %lld\n",r,cnt);
    for (int i=1;i<=cnt;i++){
        printf("%lld ",ans[i]);
    }
}

Guess you like

Origin www.cnblogs.com/lql-nyist/p/12629446.html
Recommended