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. Mpairs 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 Ncryptocurrencies 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, Cyand 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 ≤ 105
- 1 ≤ Cx, Cy ≤ N
- 1 ≤ Cxy ≤ 109
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<cmath> #include<cstdlib> #include<algorithm> #include<cstring> #include <queue> #include <vector> #include<bitset> #include<map> #include<deque> #include<stack> using namespace std; typedef pair<int,int> pii; #define X first #define Y second #define pb push_back #define mp make_pair #define ms(a,b) memset(a,b,sizeof(a)) const int inf = 0x3f3f3f3f; const int maxn = 1e5+5; const int mod = 77200211+233; #define lson l,m,2*rt #define rson m+1,r,2*rt+1 typedef long long ll; vector<pii> G[maxn]; vector<int> g[maxn]; int indeg[maxn]; int n,m; int pre[maxn],lowlink[maxn],sccno[maxn],dfs_block,scc_cnt; stack<int> S; void dfs(int u,int lim){ pre[u]=lowlink[u]=++dfs_block; S.push(u); for(int i=0;i<G[u].size();i++){ if(G[u][i].Y>lim) continue; int v=G[u][i].X; if(!pre[v]){ dfs(v,lim); lowlink[u]=min(lowlink[u],lowlink[v]); }else if(!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if(lowlink[u]==pre[u]){ scc_cnt++; while(1){ int x=S.top();S.pop(); sccno[x]=scc_cnt; if(x==u) break; } } return; } void find_scc(int n,int lim){ dfs_block=scc_cnt=0; ms(sccno,0); ms(pre,0); for(int i=1;i<=n;i++){ if(!pre[i]) dfs(i,lim); } return; } bool check(int mid){ ms(indeg,0); for(int i=0;i<=scc_cnt;i++){ g[i].clear(); } find_scc(n,mid); for(int i=1;i<=n;i++){ for(int j=0;j<G[i].size();j++){ int u,v,w; u=i; v=G[i][j].X; w=G[i][j].Y; if(w>mid) continue; if(sccno[u]==sccno[v]) continue; g[sccno[u]].pb(sccno[v]); indeg[sccno[v]]++; } } queue<int> que; for(int i=1;i<=scc_cnt;i++) if(indeg[i]==0) que.push(i); vector<int> topu; while(!que.empty()){ int now=que.front(); que.pop(); topu.pb(now); for(int i=0;i<g[now].size();i++){ indeg[g[now][i]]--; if(indeg[g[now][i]]==0){ que.push(g[now][i]); } } } if(topu.size()<=1) return true; for(int i=0;i<topu.size()-1;i++){ int now=topu[i]; bool flag=0; for(int j=0;j<g[now].size();j++){ int tmp=g[now][j]; if(tmp==topu[i+1]){ flag=1; break; } } if(!flag){ return false; } } return true; } void solve(){ int l=1,r=1e9+5; int mid; int ans=inf; while(l<=r){ mid=(l+r)>>1; if(check(mid)){ r=mid-1; ans=min(mid,ans); }else l=mid+1; } if(ans==inf) puts("Impossible"); else printf("%d ",ans); } int main(){ #ifdef LOCAL freopen("in.txt","r",stdin); #endif // LOCAL int t,u,v,w; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) G[i].clear(); for(int i=0;i<m;i++){ scanf("%d%d%d",&u,&v,&w); G[u].pb(mp(v,w)); } solve(); } return 0; }