A country named Berland has n cities. They are numbered with integers from 1 to n. City with index 1 is the capital of the country. Some pairs of cities have monodirectional roads built between them. However, not all of them are in good condition. For each road we know whether it needs repairing or not. If a road needs repairing, then it is forbidden to use it. However, the Berland government can repair the road so that it can be used.
Right now Berland is being threatened by the war with the neighbouring state. So the capital officials decided to send a military squad to each city. The squads can move only along the existing roads, as there‘s no time or money to build new roads. However, some roads will probably have to be repaired in order to get to some cities.
Of course the country needs much resources to defeat the enemy, so you want to be careful with what you‘re going to throw the forces on. That‘s why the Berland government wants to repair the minimum number of roads that is enough for the military troops to get to any city from the capital, driving along good or repaired roads. Your task is to help the Berland government and to find out, which roads need to be repaired.
Input
The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 105) — the number of cities and the number of roads in Berland.
Next m lines contain three space-separated integers ai, bi, ci (1 ≤ ai, bi ≤ n, ai ≠ bi, 0 ≤ ci ≤ 1), describing the road from city ai to city bi. If ci equals 0, than the given road is in a good condition. If ci equals 1, then it needs to be repaired.
It is guaranteed that there is not more than one road between the cities in each direction.
Output
If even after all roads are repaired, it is still impossible to get to some city from the capital, print - 1. Otherwise, on the first line print the minimum number of roads that need to be repaired, and on the second line print the numbers of these roads, separated by single spaces.
The roads are numbered starting from 1 in the order, in which they are given in the input.
If there are multiple sets, consisting of the minimum number of roads to repair to make travelling to any city from the capital possible, print any of them.
If it is possible to reach any city, driving along the roads that already are in a good condition, print 0 in the only output line.
Examples
Input3 2Output
1 3 0
3 2 1
1Input
2
4 4Output
2 3 0
3 4 0
4 1 0
4 2 1
-1Input
4 3Output
1 2 0
1 3 0
1 4 0
0
题解:
题目意思是:给你有向路径,0表示可以走,1表示这条路需要修复才能走,问你要让1号点能走到所有点的最小花费是多少。
思路:最小树形图就是最小代价,输出边的话,就是在zhuliu算法中的缩环的过程中记录需要增加的边和要删除的边,最后倒着处理一遍,剩下的边就是最小树形图上的边。
我们字需要输出边的类型为1的边即可。
参考代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define pii pair<int,int> #define pil pair<int,ll> #define mkp make_pair const int INF=0x3f3f3f3f; const int maxn=1e6+10; struct Edge{ int x,y,w; int id,real; } edge[maxn]; int vis[maxn],id[maxn],in[maxn],pre[maxn]; int lastEdge[maxn],used[maxn]; int addEdge[maxn],delEdge[maxn]; int zhuliu(int root,int n,int m) { int res=0,edgeNum=m; while(true) { for(int i=1;i<=n;++i) in[i]=INF; for(int i=1;i<=m;++i)//找到每个点的最小入边及其编号 { int x=edge[i].x,y=edge[i].y; if(edge[i].w<in[y] && x!=y) { pre[y]=x; in[y]=edge[i].w; lastEdge[y]=edge[i].id; } } for(int i=1;i<=n;++i)//判断是否可以形成最小树形图 { if(i==root) continue; if(in[i]==INF) return -1; } int cnt=0; in[root]=0; memset(id,-1,sizeof id); memset(vis,-1,sizeof vis); for(int i=1;i<=n;++i) { res+=in[i]; if(i!=root) used[lastEdge[i]]++; int y=i; while(vis[y]!=i&&id[y]==-1&&y!=root) { vis[y]=i; y=pre[y]; } if(y!=root && id[y]==-1) { cnt++; for(int x=pre[y];x!=y;x=pre[x]) id[x]=cnt; id[y]=cnt; } } if(cnt==0) break; for(int i=1;i<=n;++i)//独立点 if(id[i]==-1) id[i]=++cnt; for(int i=1;i<=m;++i) { int x=edge[i].x,y=edge[i].y; edge[i].x=id[x];edge[i].y=id[y]; if(id[x]!=id[y]) { edge[i].w-=in[y]; delEdge[++edgeNum]=lastEdge[y]; addEdge[edgeNum]=edge[i].id; edge[i].id=edgeNum; } } n=cnt; root=id[root]; } for(int i=edgeNum;i>m;--i) { if(used[i]) { --used[delEdge[i]]; ++used[addEdge[i]]; } } return res; } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].w); edge[i].id=i; edge[i].real=edge[i].w; } int res=zhuliu(1,n,m); if(res==-1||res==0) printf("%d\n",res); else { printf("%d\n",res); for(int i=1;i<=m;++i) { if(used[i]&&edge[i].real) printf("%d ",i); } puts(""); } return 0; }View Code