二分花费,保证大于的不成环,然后拓扑排序,保证连边的单向
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
int n,m;
struct node
{
int u,v,c,id;
}itm[100005];
vector<node>e[100005];
int c[100005];
int vis[100005];
int fail;
void dfs1(int u,int f)
{
if(fail==1)
return;
vis[u]=1;
int len=e[u].size();
for(int i=0;i<len;i++)
{
int v=e[u][i].v;
int tc=e[u][i].c;
if(tc<=f)
continue;
if(vis[v]==1)
{
fail=1;return;
}
else
{
dfs1(v,f);
}
}
vis[u]=2;
}
bool check(int mid)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
fail=0;
dfs1(i,c[mid]);
if(fail==1)
return false;
}
}
return true;
}
int bin()
{
int l=0,r=m;
while(l<r)
{
int mid=(l+r)/2;
if(check(mid))
r=mid;
else
l=mid+1;
}
return r;
}
int ans2;
vector<int>ans;
int in[100005];
int sid[100005];
int main() {
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<=100000;i++)
e[i].clear(),vis[i]=0,in[i]=0;
ans.clear();
c[0]=0;
for(int i=0;i<m;i++)
{
int u,v,tc;
scanf("%d%d%d",&u,&v,&tc);
node tp;tp.v=v;tp.c=tc;tp.id=i+1;tp.u=u;
e[u].push_back(tp);
c[i+1]=tc;
itm[i]=tp;
}
sort(c,c+m+1);
int ans1=bin();
ans2=0;
queue<int> q;
for(int i=0;i<m;i++)
{
if(itm[i].c>c[ans1])
{
in[itm[i].v]++;
}
}
for(int i=1;i<=n;i++)
{
if(in[i]==0)
q.push(i);
}
int cnt=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
sid[cur]=cnt++;
int len=e[cur].size();
for(int i=0;i<len;i++)
{
if(e[cur][i].c>c[ans1])
{
in[e[cur][i].v]--;
if(in[e[cur][i].v]==0)
q.push(e[cur][i].v);
}
}
}
for(int i=0;i<m;i++)
{
if(itm[i].c<=c[ans1])
{
if(sid[itm[i].u]>sid[itm[i].v])
ans2++,ans.push_back(itm[i].id);
}
}
printf("%d %d\n",c[ans1],ans2);
int len=ans.size();
for(int i=0;i<len;i++)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}