Breaking Good

time limit per test 2 seconds

memory limit per test 256 megabytes

Breaking Good is a new video game which a lot of gamers want to have. There is a certain level in the game that is really difficult even for experienced gamers.

Walter William, the main character of the game, wants to join a gang called Los Hermanos (The Brothers). The gang controls the whole country which consists of n cities with m bidirectional roads connecting them. There is no road is connecting a city to itself and for any two cities there is at most one road between them. The country is connected, in the other words, it is possible to reach any city from any other city using the given roads.

The roads aren't all working. There are some roads which need some more work to be performed to be completely functioning.

The gang is going to rob a bank! The bank is located in city 1. As usual, the hardest part is to escape to their headquarters where the police can't get them. The gang's headquarters is in city n. To gain the gang's trust, Walter is in charge of this operation, so he came up with a smart plan.

First of all the path which they are going to use on their way back from city 1 to their headquarters n must be as short as possible, since it is important to finish operation as fast as possible.

Then, gang has to blow up all other roads in country that don't lay on this path, in order to prevent any police reinforcements. In case of non-working road, they don't have to blow up it as it is already malfunctional.

If the chosen path has some roads that doesn't work they'll have to repair those roads before the operation.

Walter discovered that there was a lot of paths that satisfied the condition of being shortest possible so he decided to choose among them a path that minimizes the total number of affected roads (both roads that have to be blown up and roads to be repaired).

Can you help Walter complete his task and gain the gang's trust?

Input

The first line of input contains two integers n, m (2 ≤ n ≤ 105, ), the number of cities and number of roads respectively.

In following m lines there are descriptions of roads. Each description consists of three integers x, y, z (1 ≤ x, y ≤ n, ) meaning that there is a road connecting cities number x and y. If z = 1, this road is working, otherwise it is not.

Output

In the first line output one integer k, the minimum possible number of roads affected by gang.

In the following k lines output three integers describing roads that should be affected. Each line should contain three integers x, y, z (1 ≤ x, y ≤ n, ), cities connected by a road and the new state of a road. z = 1 indicates that the road between cities x and y should be repaired and z = 0 means that road should be blown up.

You may output roads in any order. Each affected road should appear exactly once. You may output cities connected by a single road in any order. If you output a road, it's original state should be different from z.

After performing all operations accroding to your plan, there should remain working only roads lying on some certain shortest past between city 1 and n.

If there are multiple optimal answers output any.

Examples

input

2 1

1 2 0

output

1

1 2 1

input

4 4

1 2 1

1 3 0

2 3 1

3 4 1

output

3

1 2 0

1 3 1

2 3 0

input

8 9

1 2 0

8 3 0

2 3 1

1 4 1

8 7 0

1 5 1

4 6 1

5 7 0

6 8 0

output

3

2 3 0

1 5 0

6 8 1

Note

In the first test the only path is 1 - 2

In the second test the only shortest path is 1 - 3 - 4

In the third test there are multiple shortest paths but the optimal is 1 - 4 - 6 - 8





大概意思就是给定 n 个点, m 条边的有向图,边权都为 1,一些需要维修。

你需要选择1条 1 到 n 的最短路,将它们修好,并炸毁其它所

有不在路径上的完好的路。

若有多条最短路,选择影响值最小的。

影响值 = 维修的路数 + 炸毁的路数。



我大概想了一下,应该就是找一条最短路上的边权最大。。。

然后这个dp是按照dis转移的,必须是dis + 1才可以满足最短路。。。

但是好像可以分层图啥的。。。不会啊


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct lpl{
int to, dis;
}lin, from[maxn];
struct ld{
int a, b;
bool operator < (const ld &A)const{
if(a == A.a) return b < A.b;
return a < A.a;
}
}asd;
int n, m, r, sum, dis[maxn], f[maxn];
bool vis[maxn];
vector<int> edge[maxn];
vector<lpl> point[maxn];
queue<int> q;
set<ld> s; inline void putit()
{
scanf("%d%d", &n, &m);
for(int a, b, i = 1; i <= m; ++i){
scanf("%d%d%d", &a, &b, &lin.dis); sum += lin.dis;
edge[a].push_back(b); edge[b].push_back(a);
lin.to = b; point[a].push_back(lin);
lin.to = a; point[b].push_back(lin);
}
} inline void spfa()
{
int now, qwe; q.push(1); memset(dis, 0x3f, sizeof(dis)); dis[1] = 0;
while(!q.empty()){
now = q.front(); q.pop(); vis[now] = false;
for(int i = edge[now].size() - 1; i >= 0; --i){
qwe = edge[now][i];
if(dis[qwe] > dis[now] + 1){
dis[qwe] = dis[now] + 1;
if(!vis[qwe]){
vis[qwe] = true; q.push(qwe);
}
}
}
}
} int dp(int t)
{
if(vis[t]) return f[t];
vis[t] = true;
for(int i = point[t].size() - 1; i >= 0; --i){
int now = point[t][i].to;
if(dis[t] != dis[now] + 1) continue;
if(f[t] <= dp(now) + point[t][i].dis){
f[t] = f[now] + point[t][i].dis;
from[t].to = now; from[t].dis = point[t][i].dis;
}
}
return f[t];
} inline void workk()
{
printf("%d\n", sum + dis[n] - 2 * dp(n)); int t = n;
while(t != 1){
asd.a = t; asd.b = from[t].to;
if(asd.a > asd.b) swap(asd.a, asd.b); s.insert(asd); t = from[t].to;
}
for(int i = 1; i <= n; ++i){
for(int j = point[i].size() - 1; j >= 0; --j){
lin = point[i][j]; if(lin.to > i) continue;
asd.a = lin.to; asd.b = i;
if(s.count(asd)){
if(!lin.dis) printf("%d %d 1\n", asd.a, asd.b);
}
else{
if(lin.dis) printf("%d %d 0\n", asd.a, asd.b);
}
}
}
} int main()
{
putit();
spfa();
workk();
return 0;
}

最新文章

  1. Web工作原理
  2. Web 开发精华文章集锦(jQuery、HTML5、CSS3)【系列二十七】
  3. Sqoop_ 简单介绍
  4. Android MonkeyRunner自动拨打电话
  5. tomcat配置多实例
  6. Android中获取网页表单中的数据实现思路及代码
  7. or1200乘法除法指令解释
  8. 如何高效的用判断用js判断ie6
  9. page分页类
  10. JavaScript中的数组对象遍历、读写、排序等操作
  11. delphi 10.1 Berlin 中使用自带的 MD5 校验
  12. IDAPython教程(三)
  13. C# 之 反射性能优化3
  14. 3. Spring 核心之 IOC(控制反转) &amp; DI(依赖注入)
  15. 私服仓库 nexus 环境搭建(win10)
  16. 洗礼灵魂,修炼python(58)--爬虫篇—【转载】urllib3模块
  17. NBUT 1217 Dinner 2010辽宁省赛
  18. ArcGIS案例学习笔记4_2
  19. 关于jquery的serialize方法转换空格为+号的解决方法
  20. 【BZOJ1835】基站选址(线段树)

热门文章

  1. Java JNA (二)—— dll回调函数实现
  2. 【linux 进程杀死】批量杀死进程
  3. skiasharp在阿里云Windows server 2016上部署时提示The type initializer for &#39;SkiaSharp.SKAbstractManagedStream&#39; threw an exception. 错误
  4. 数据库与缓存:2.Redis数据库的基本知识
  5. zookeeper,通过python连接找出其对应的hive
  6. CentOS7.5 开启Samba服务
  7. 0-2马尔可夫过程Markov Processes
  8. java生成快递单并调用打印机打印
  9. docker 报错端口被占用 sqlserver 占用80端口
  10. Vue学习笔记-组件通信-父传子(props中的驼峰标识)