链接:https://cn.vjudge.net/contest/259386#problem/H
思路: 二分 ans 然后judge judge 的时候先缩点然后生成一个DAG图,然后跑出一个topo序列,然后判断相邻的两个点之间是否有连边没有则不满足。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf =0x3f3f3f3f;
typedef pair<int ,int > pii;
const int N = 100005;
int n,m;
vector< pii >ve1[N],ve[N];
int outde[N];
int inde[N];
int ins[N];
int st[N];
int low[N],belong[N],dfn[N];
int top;
int Index;
int scc;
set<int >se[N];
void tarjan(int u)
{
int v;
low[u]=dfn[u]=++Index;
st[top++]=u;
ins[u]=1;
for(int i=0;i<ve[u].size();i++)
{
v=ve[u][i].first;
if(!dfn[v])
{
tarjan(v);
if(low[v]<low[u]) low[u]=low[v];
}
else if(ins[v]&&dfn[v]<low[u]) low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
scc++;
//printf("*** u %d %d\n",u,scc);
do
{
v=st[--top];
ins[v]=0;
belong[v]=scc;
}while(v!=u);
}
}
void init()
{
for(int i=1;i<=n+2;i++) ve[i].clear();
for(int i=0;i<=n+2;i++)
{
ins[i]=outde[i]=st[i]=belong[i]=low[i]=dfn[i]=inde[i]=0;
}
top=Index=scc=0;
}
int jud(int mid)
{
init();
for(int i=1;i<=n;i++)
{
for(int j=0;j<ve1[i].size();j++)
{
if(ve1[i][j].second<=mid)
{
ve[i].push_back(ve1[i][j]);
// printf("******* %d %d %d\n",i,ve1[i][j].first,ve1[i][j].second);
// printf("******* %d %d %d\n",i,ve[i][j].first,ve[i][j].second);
}
}
}
int uu,vv,u,v;
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
}
if(scc==1) return 1;
for(int i=0;i<=n+2;i++) se[i].clear();
for(int i=0;i<=n+2;i++) inde[i]=0;
for(int i=1;i<=n;i++)
{
uu=i;
for(int j=0;j<ve[i].size();j++)
{
vv=ve[i][j].first;
//printf("**&&&&& uv %d %d\n",uu,vv);
u=belong[uu];
v=belong[vv];
if(u==v) continue;
if(se[u].count(v)==0)
{
se[u].insert(v);
//printf("hHHHHh %d %d\n",u,v);
inde[v]++;
}
}
}
/*
for(int i=1;i<=scc;i++)
{
for(set<int >::iterator it=se[i].begin();it!=se[i].end();it++)
{
printf("** %d %d\n",i,*it);
}
}
*/
vector< int >topo;
int f=0;
queue< int >q;
for(int i=1;i<=scc;i++)
{
if(inde[i]==0)
{
q.push(i);
}
}
while(!q.empty())
{
u=q.front(); q.pop();
topo.push_back(u);
for(set<int >::iterator it=se[u].begin();it!=se[u].end();it++)
{
v=*it;
inde[v]--;
if(inde[v]==0)
{
q.push(v);
}
}
}
if(topo.size()!=scc) return 0;
if(topo.size()<=1) return 1;
f=0;
for(int i=0;i<topo.size()-1;i++)
{
u=topo[i]; v=topo[i+1];
if(se[u].count(v)==0)
{
f=1; break;
}
}
if(f) return 0;
return 1;
}
void init1()
{
for(int i=0;i<=n+2;i++)
{
ve[i].clear();
ve1[i].clear();
}
memset(st,0,sizeof(st));
memset(ins,0,sizeof(ins));
memset(outde,0,sizeof(outde));
memset(inde,0,sizeof(inde));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(dfn,0,sizeof(dfn));
top=Index=scc=0;
}
int main()
{
int u,v,w;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
init1();
int L,R;
R=-1;
L=inf;
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&u,&v,&w);
ve1[u].push_back(pii(v,w));
L=min(L,w);
R=max(R,w);
}
int mid;
int ans=-1;
while(L<=R)
{
mid=(L+R)>>1;
if(jud(mid))
{
ans=mid;
R=mid-1;
}
else L=mid+1;
}
if(ans==-1)
{
printf("Impossible\n");
}
else printf("%d\n",ans);
}
return 0;
}
/*
5
4 3
1 2 1
2 3 1
2 4 1
*/