1 #include<iostream>
2 using namespace std;
3 #include<cstdio>
4 #include<cstring>
5 #define MAXN 1005
6 #define INF 0x7f7f7f7f
7 typedef __int64 type;
8 struct node//边的权和顶点
9 {
10 int u, v;
11 type w;
12 }edge[MAXN * MAXN];
13 int pre[MAXN], id[MAXN], vis[MAXN], n, m, pos;
14 type in[MAXN];//存最小入边权,pre[v]为该边的起点
15 type Directed_MST(int root, int V, int E)
16 {
17 type ret = 0;//存最小树形图总权值
18 while(true)
19 {
20 int i;
21 //1.找每个节点的最小入边
22 for( i = 0; i < V; i++)
23 in[i] = INF;//初始化为无穷大
24 for( i = 0; i < E; i++)//遍历每条边
25 {
26 int u = edge[i].u;
27 int v = edge[i].v;
28 if(edge[i].w < in[v] && u != v)//说明顶点v有条权值较小的入边 记录之
29 {
30 pre[v] = u;//节点u指向v
31 in[v] = edge[i].w;//最小入边
32 if(u == root)//这个点就是实际的起点
33 pos = i;
34 }
35 }
36 for( i = 0; i < V; i++)//判断是否存在最小树形图
37 {
38 if(i == root)
39 continue;
40 if(in[i] == INF)
41 return -1;//除了根以外有点没有入边,则根无法到达它 说明它是独立的点 一定不能构成树形图
42 }
43 //2.找环
44 int cnt = 0;//记录环数
45 memset(id, -1, sizeof(id));
46 memset(vis, -1, sizeof(vis));
47 in[root] = 0;
48 for( i = 0; i < V; i++) //标记每个环
49 {
50 ret += in[i];//记录权值
51 int v = i;
52 while(vis[v] != i && id[v] == -1 && v != root)
53 {
54 vis[v] = i;
55 v = pre[v];
56 }
57 if(v != root && id[v] == -1)
58 {
59 for(int u = pre[v]; u != v; u = pre[u])
60 id[u] = cnt;//标记节点u为第几个环
61 id[v] = cnt++;
62 }
63 }
64 if(cnt == 0)
65 break; //无环 则break
66 for( i = 0; i < V; i++)
67 if(id[i] == -1)
68 id[i] = cnt++;
69 //3.建立新图 缩点,重新标记
70 for( i = 0; i < E; i++)
71 {
72 int u = edge[i].u;
73 int v = edge[i].v;
74 edge[i].u = id[u];
75 edge[i].v = id[v];
76 if(id[u] != id[v])
77 edge[i].w -= in[v];
78 }
79 V = cnt;
80 root = id[root];
81 }
82 return ret;
83 }
84 int main()
85 {
86 int i;
87 while(scanf("%d%d", &n, &m) != EOF)
88 {
89 type sum = 0;
90 for( i = 0; i < m; i++)
91 {
92 scanf("%d%d%I64d", &edge[i].u, &edge[i].v, &edge[i].w);
93 edge[i].u++; edge[i].v++;
94 sum += edge[i].w;
95 }
96 sum ++;
97 for( i = m; i < m + n; i++)//增加超级节点0,节点0到其余各个节点的边权相同(此题中 边权要大于原图的总边权值)
98 {
99 edge[i].u = 0;
100 edge[i].v = i - m + 1;
101 edge[i].w = sum;
102 }
103 type ans = Directed_MST(0, n + 1, m + n);
104 //n+1为总结点数,m+n为总边数
105 //ans代表以超级节点0为根的最小树形图的总权值,
106 //将ans减去sum,如果差值小于sum,说明节点0的出度只有1,说明原图是连通图
107 //如果差值>=sum,那么说明节点0的出度不止为1,说明原图不是连通图
108 if(ans == -1 || ans - sum >= sum)
109 puts("impossible");
110 else
111 printf("%I64d %d\n",ans - sum, pos - m);
112 puts("");
113 }
114 return 0;
115 }