/*给你有向图,有些边是可以直接走的,有些边是修之后才可以走,现在要想从1能到达所有的点,问你至少要修多少条路。 解:现把 可以直接 走的边加进来,缩点,因为(1<n,m<1e6)。 然后从1点bfs,每个点初始都为0,可以直接的标记为-1,要修的边标记为边的编号,当再有不修路就能到达的话又把它标记为-1,。 所以,如果路全部修之后好不能到达,则有些点还为0。 点的标记>0,则说明修路之后才能到达。 要记录边的编号,应该用数组模拟邻接链表。 */ #include<cstdio> #include<cstring> #include<iostream> #define N 100030 using namespace std; int head[N]; int n,m,x,y; int dfn[N],low[N],instack[N],num[N],edge[N],f[N],o[N],top,D,now,ans; bool inst[N]; struct Node { int u,v,f; int next; }ed[N]; void tarjan(int i) { dfn[i]=low[i]=++D; inst[i]=1,instack[++top]=i; for (int p=head[i]; p; p=ed[p].next) { int j=ed[p].v; if(ed[p].f)continue; if (!dfn[j]) tarjan(j),low[i]=min(low[i],low[j]); else if (inst[j]) low[i]=min(low[i],dfn[j]); } if (low[i]==dfn[i]) { now++; int k; do k=instack[top--],inst[k]=0,num[k]=now; while (k!=i); } } void bfs(int x) { int h=0,t=1; f[1]=x; edge[x]=-1; while (h<t) { int i=f[++h]; for (int p=head[i]; p; p=ed[p].next) { //int j=vv[p]; int j=ed[p].v; if (!edge[j]) edge[j]=ed[p].f ?p:-1,f[++t]=j; else if (edge[j]>0 && !ed[p].f) edge[j]=-1; } } } void init() { memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(edge,0,sizeof(edge)); top=0; D=0; now=0; } void add(int u,int v,int f,int e) { ed[e].u=u; ed[e].v=v; ed[e].f=f; ed[e].next=head[u]; head[u]=e; } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); while(scanf("%d%d",&n,&m)!=EOF) { init(); int u,v,f; for (int i=1; i<=m; i++) { cin>>u>>v>>f; add(u,v,f,i); } for (int i=1; i<=n; i++) if (!dfn[i]) tarjan(i); memset(head,0,sizeof(head)); for (int i=1; i<=m; i++) { //int x=num[uu[i]],y=num[vv[i]]; //vv[i]=y; // if (x!=y) next[i]=head[x],head[x]=i; int x=num[ed[i].u]; int y=num[ed[i].v]; int f=ed[i].f; if(x!=y) { add(x,y,f,i); } } bfs(num[1]); ans=0; for (int i=1; i<=now; i++) if (edge[i]>0) o[++ans]=edge[i]; for (int i=1; i<=now; i++) if (!edge[i]) ans=-1; printf("%d\n",ans); for (int i=1; i<=ans; i++) printf("%d%s",o[i],i<ans?" ":"\n"); } return 0; }