Breaking Good

Posted 蔡军帅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Breaking Good相关的知识,希望对你有一定的参考价值。

Time limit2000 ms

Memory limit262144 kB

 

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 ncities 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条边,每条边有编号z=1边是好的,z=0边是坏的,问从点1出发到点n的最短路,当最短路有多条时取修正值小的结果。修正的值=多余的好路(边)+要用的坏路(边),输入输出有格式。

分析:最短路+记录前驱

 

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=200005;
int n,m,sum;
int book[maxn];
struct node
{
    int c;
    int v;
};
struct edge
{
    int a,b,c;
}e[maxn];
vector<node>v[maxn];
queue<int>q;
int n0[maxn];
int n1[maxn];
int t[maxn];
int pra[maxn];
int main()
{
    scanf("%d %d",&n,&m);
    sum=0;
    for(int i=1;i<=n;i++)
    {
        pra[i]=i;
        n0[i]=0;
        n1[i]=0;
        book[i]=0;
    }
    memset(t,inf,sizeof(t));
    for(int i=1;i<=m;i++)
    {
        int x,y,c;
        scanf("%d %d %d",&x,&y,&c);
        if(c==1) sum++;//记录1的个数
        e[i].a=x;
        e[i].b=y;
        e[i].c=c;
        node a;
        a.v=y;
        a.c=c;
        v[x].push_back(a);
        a.v=x;
        a.c=c;
        v[y].push_back(a);
    }
    while(!q.empty()) q.pop();
    q.push(1);
    t[1]=1;
    n0[1]=0;//这条路上有几个0
    n1[1]=0;//有几个1
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=0;i<v[x].size();i++)
        {
            node a=v[x][i];
            int y=a.v;
            if(t[y]>t[x]+1)//用来记录路径的长短
            {//选路径短的
                t[y]=t[x]+1;
                if(a.c==0) n0[y]=n0[x]+1;
                else n0[y]=n0[x];
                if(a.c==1) n1[y]=n1[x]+1;
                else n1[y]=n1[x];
                pra[y]=x;//记录路径,不能写成pra【x】=y
                q.push(y);
             }
             else if(t[y]==t[x]+1)
             {//如果路径相同
                 if(n0[y]>n0[x])
                 {//选0的个数少的,因为0少,修的路少,路径相同的情况下,0少1就多
                     if(a.c==0) n0[y]=n0[x]+1;
                     else n0[y]=n0[x];
                     if(a.c==1) n1[y]=n1[x]+1;
                     else n1[y]=n1[x];
                     pra[y]=x;
                 }
                 q.push(y);
             }
        }

    }
    //cout<<n0[n]<<" "<<n1[n]<<endl;
    //cout<<sum<<endl;
   printf("%d",n0[n]+sum-n1[n]);//输出的是0的个数,总共1的个数-当前路的1的个数
    int k=n;
    //cout<<pra[1]<<" "<<pra[4]<<" "<<pra[6]<<endl;
    while(pra[k]!=k)//整理一下
    {
        book[k]=1;
        k=pra[k];
    }
    for(int i=1;i<=n;i++)
    {
        if(!book[i])
        {
            pra[i]=i;//该恢复的恢复
        }
    }
    for(int i=1;i<=m;i++)
    {
        edge x=e[i];
        if(pra[x.a]!=x.b&&pra[x.b]!=x.a&&x.c==1)
        {
            printf("\n");
            printf("%d %d %d",x.a,x.b,0);

        }
        else if(pra[x.a]==x.b||pra[x.b]==x.a)
        {
            if(x.c==0)
            {
                printf("\n");
            printf("%d %d %d",x.a,x.b,1);
            }
        }
    }
    return 0;
}

 






















以上是关于Breaking Good的主要内容,如果未能解决你的问题,请参考以下文章

向Linus学习,让代码具有good taste

code-breaking picklecode中对signed_cookies引擎分析

Doors Breaking and Repairing CodeForces - 1102C (思维)

Breaking Biscuits(模板题-求凸边形的宽)

编程杂谈——Non-breaking space

Doors Breaking and Repairing