codeforces1100E. Andrew and Taxi(拓扑排序+二分)

E. Andrew and Taxi

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Andrew prefers taxi to other means of transport, but recently most taxi drivers have been acting inappropriately. In order to earn more money, taxi drivers started to drive in circles. Roads in Andrew’s city are one-way, and people are not necessary able to travel from one part to another, but it pales in comparison to insidious taxi drivers.

The mayor of the city decided to change the direction of certain roads so that the taxi drivers wouldn’t be able to increase the cost of the trip endlessly. More formally, if the taxi driver is on a certain crossroads, they wouldn’t be able to reach it again if he performs a nonzero trip.

Traffic controllers are needed in order to change the direction the road goes. For every road it is known how many traffic controllers are needed to change the direction of the road to the opposite one. It is allowed to change the directions of roads one by one, meaning that each traffic controller can participate in reversing two or more roads.

You need to calculate the minimum number of traffic controllers that you need to hire to perform the task and the list of the roads that need to be reversed.

Input

The first line contains two integers nn and mm (2≤n≤1000002≤n≤100000, 1≤m≤1000001≤m≤100000) — the number of crossroads and the number of roads in the city, respectively.

Each of the following mm lines contain three integers uiui, vivi and cici (1≤ui,vi≤n1≤ui,vi≤n, 1≤ci≤1091≤ci≤109, ui≠viui≠vi) — the crossroads the road starts at, the crossroads the road ends at and the number of traffic controllers required to reverse this road.

Output

In the first line output two integers the minimal amount of traffic controllers required to complete the task and amount of roads kkwhich should be reversed. kk should not be minimized.

In the next line output kk integers separated by spaces — numbers of roads, the directions of which should be reversed. The roads are numerated from 11 in the order they are written in the input. If there are many solutions, print any of them.

Examples

input

Copy

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

output

Copy

2 2
1 3 

input

Copy

5 7
2 1 5
3 2 3
1 3 3
2 4 1
4 3 5
5 4 1
1 5 3

output

Copy

3 3
3 4 7 

Note

There are two simple cycles in the first example: 1→5→2→11→5→2→1 and 2→3→4→5→22→3→4→5→2. One traffic controller can only reverse the road 2→12→1 and he can’t destroy the second cycle by himself. Two traffic controllers can reverse roads 2→12→1 and 2→32→3 which would satisfy the condition.

In the second example one traffic controller can’t destroy the cycle 1→3→2→11→3→2→1. With the help of three controllers we can, for example, reverse roads 1→31→3 ,2→42→4, 1→51→5.

 

一、原题地址

点我传送

 

二、大致题意

  给出n个点,m条单向的边。每条边有它的权值,表示需要w个控制器才能使这条单向的路翻转。

  询问的是,要使得给出的图不存在环所需的最少控制器的数量,以及需要翻转哪些边,输出边的编号。(控制器是可以被多次使用的,即问题所求的是最少的需求数)。

 

三、大致思路

    二分枚举最少需要的控制器的数量 mid,首先那些权值大于 mid 的路我们当前是一定没办法翻转的所以建立单向边。暂时去掉那些权值小于mid的边跑拓扑排序。

    如果构成了有环的路,说明枚举的mid偏小了;否则我们才开始尝试把那些之前暂时去掉的边加入,在加入边的时候就用上了之前排序时得到的等级,先被排序好的部分往后面的部分建立单向边是一定不会导致环产生的

 

四、代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;


int n,m;
vector<int>e[100005],Ansid;
queue<int>q;
int inde[100005];
int tp[100005],tot;
struct edge
{
    int u,v,w;
}ed[100005];

void read()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)scanf("%d %d %d",&ed[i].u,&ed[i].v,&ed[i].w);
}

void init()
{
    for(int i=1;i<=n;i++)
    {
        e[i].clear();
        inde[i]=0;
    }
    tot=0;
}

void Topu()
{
    for(int i=1;i<=n;i++)
    {
        if(inde[i]==0)
        {
            tp[i]=tot++;
            q.push(i);
        }
    }
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        int Size=e[t].size();
        for(int i=0;i<Size;i++)
        {
            int to=e[t][i];
            inde[to]--;
            if(inde[to]==0)
            {
                q.push(to);
                tp[to]=tot++;
            }
        }
    }
}

bool check(int mid)
{
    init();
    for(int i=1;i<=m;i++)
    {
        if(ed[i].w>mid)
        {
            e[ed[i].u].push_back(ed[i].v);
            inde[ed[i].v]++;
        }
    }
    Topu();
    for(int i=1;i<=n;i++)
    {
        if(inde[i]>0)return false;
    }
    Ansid.clear();
    for(int i=1;i<=m;i++)
    {
        if(ed[i].w<=mid&&tp[ed[i].u]>tp[ed[i].v])Ansid.push_back(i);
    }
    return true;
}

int main()
{
    read();
    int l=0,r=1e9,mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid))
        {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    int minn=0;
    int Size=Ansid.size();
    for(int i=0;i<Size;i++)
    {
        minn=max(minn,ed[Ansid[i]].w);
    }
    printf("%d %d\n",minn,Size);
    for(int i=0;i<Size;i++)
    {
        printf("%d ",Ansid[i]);
    }
}

 

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/Amovement/article/details/86513163
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞