【CodeChef - CRYPCUR】Crypto Trading(二分套tarjan、拓扑排序)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Coldfresh/article/details/83146333

AMRExchange is the latest cryptocurrency exchange that has become very popular among cryptocurrency traders.

On AMRExchange, there are N cryptocurrencies - let us denote the ith currency by Ci. M pairs of these cryptocurrencies are tradable - one unit of currency Cx can be converted to one unit of currency Cy with risk Cxy.

Mr. X, an avid cryptocurrency collector, wants to start with 1 unit of any of the N cryptocurrencies and perform a sequence of trades. He wants to do it in such a way that for each of the N cryptocurrencies, there was at least one point during the trading sequence during which he held one unit of that cryptocurrency.

The overall risk of the sequence of trades is the maximum risk in the sequence of trades. Minimize the overall risk with which Mr. X can achieve this. Print “Impossible” if no such sequence of trades is possible.

Input
The first line contains a single integer T - the total number of testcases.
Each testcase is of the following format:
First line contains 2 space-separated integers - N and M. N denotes the number of cryptocurrencies, M denotes the number of tradable ordered cryptocurrency pairs.
M lines follow. Each line contains 3 space-separated positive integers - Cx, Cy and Cxy. This line denotes that one unit of currency Cx can be converted into one unit of currency Cy with risk Cxy.
Output
For each testcase, print the minimum overall risk with which Mr. X can own at least one unit of each cryptocurrency at some point in time.
If it is not possible for Mr. X to achieve this, then print “Impossible”.
Constraints
1 ≤ T ≤ 5
1 ≤ N, M ≤ 10^5
1 ≤ Cx, Cy ≤ N
1 ≤ Cxy ≤ 10^9
Example
Input
2
3 6
1 2 1
2 3 3
3 1 3
1 3 1
3 2 1
3 2 5
4 3
1 2 1
2 3 1
2 4 1

Output
1
Impossible
Explanation
Testcase 1: Mr. X can start with cryptocurrency C1 and follow the following sequence to minimize overall risk:

Convert C1 to C3 with risk 1.
Convert C3 to C2 with risk 1.
The overall risk would be 1.

Testcase 2: There are a total of 6 sequences of trades are possible, and none of them satisfy our property. We list them here:

Starting with C1:

C1 -> C2 -> C3
C1 -> C2 -> C4
In the first sequence, Mr. X won’t be able to own C4 because units of C3 cannot be converted to units of C4. Similarly, in the second sequence, Mr. X won’t be able to own C3 because units of C4 cannot be converted to units of C3.

Starting with C2:

C2 -> C3
C2 -> C4
Starting with C3:

C3 (cannot be converted to any other cryptocurrency)
Starting with C4:

C4 (cannot be converted to any other cryptocurrency)
Hence, there is no possible sequence using which Mr. X can own one unit of all cryptocurrencies at some point in time.

**思路:**因为答案有单调性,所以,二分枚举边权来建边,检查是否可以形成一个链。
代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define maxn 100005
using namespace std;
int n,m;
struct node
{
    int x,y,val;
}p[maxn];
int w[maxn];
vector<int> g[maxn],_g[maxn];
int dfn[maxn],low[maxn],_index;
bool inS[maxn];
int st[maxn],cnt;
int id[maxn],tot;
void tarjan(int u)
{
    dfn[u]=low[u]=++_index;
    st[++cnt]=u;inS[u]=true;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(inS[v])low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        tot++;
        int now;
        do
        {
            now=st[cnt--];
            inS[now]=false;
            id[now]=tot;
        }while(now!=u);
    }
}
int ind[maxn];
void init()
{
    memset(dfn,0,sizeof(dfn));_index=0;
    tot=0;
    memset(ind,0,sizeof(ind));
}
void build(int x)
{
    for(int i=1;i<=n;i++)g[i].clear();
    for(int i=0;i<m;i++)
    {
        if(p[i].val>x)continue;
        g[p[i].x].push_back(p[i].y);
    }
    init();
    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);

    for(int i=1;i<=n;i++)_g[i].clear();
    for(int u=1;u<=n;u++)
    {
        for(int i=0;i<g[u].size();i++)
        {
            int v=g[u][i];
            if(id[v]!=id[u])
            {
                _g[id[u]].push_back(id[v]);
                ++ind[id[v]];
            }
        }
    }
}
bool topoSort()
{
    queue<int> que;
    for(int i=1;i<=tot;i++)if(!ind[i])que.push(i);
    while(que.size())
    {
        if(que.size()>1)return false;
        int u=que.front();que.pop();
        for(int i=0;i<_g[u].size();i++)
        {
            int v=_g[u][i];
            --ind[v];
            if(!ind[v])que.push(v);
        }
    }
    return true;
}
bool check(int x)
{
    build(x);
    return topoSort();
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].val);
            w[i]=p[i].val;
        }
        sort(w,w+m);
        int l=0,r=m-1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(w[mid]))r=mid-1;
            else l=mid+1;
        }
        if(l==m)printf("Impossible\n");
        else printf("%d\n",w[l]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Coldfresh/article/details/83146333