【题意】

            N<=10^5个城市,M<=10^5条边,保证无向联通并且没有自环和重边。边分成两种,一种是被毁坏的,用0表示,一种是没被毁坏的用1表示。现在要修1-n的最短路,并且使得这条路的影响值最小,一条道路的影响值定义为:最短路上的毁坏边数+不在最短路上的正常边数。输出影响值以及影响的边。

【解题方法】

           设几个变量来看一看,all代表所有的正常边,d代表最短路,最短路上的正常边为x。所以ans = d-x+all-x = all + d -2*x!

           观察一下上面这个等式会发现,除了x其他都是常量,所以要使得答案最小只需要使得x最大就可以啦。由于图上的权值最大1,所以bfs最短路就行了,在过程中维护f[i],g[i],pre[i],分别代表最短路,最短路上的正常边,还有记录前驱。

【AC 代码】

#include <bits/stdc++.h>
using namespace std;
const int inf  = 0x3f3f3f3f;
const int maxn = 1e5+10;
const int maxm = 2e5+10;
int n,m,u,v,w,all,id,f[maxn],g[maxn],pre[maxn];
struct edge{
    int v,w,next;
}E[maxm];
int head[maxn],edge_cnt;
void init(){
    memset(head,-1,sizeof(head));
    edge_cnt=0;
}
void addedge(int u,int v,int w){
    E[edge_cnt].v=v,E[edge_cnt].w=w,E[edge_cnt].next=head[u],head[u]=edge_cnt++;
}
void bfs(){
    queue<int>que;
    for(int i=1; i<=n; i++) f[i]=inf;
    for(int i=1; i<=n; i++) g[i]=0;
    f[1]=g[1]=0;
    que.push(1);
    while(que.size()){
        int u=que.front();
        que.pop();
        for(int i=head[u]; ~i; i=E[i].next){
            int v=E[i].v,w=E[i].w;
            if(f[v]==inf){
                f[v]=f[u]+1;
                g[v]=g[u]+w;
                pre[v]=i;
                que.push(v);
            }else if(f[v]==f[u]+1){
                if(g[u]+w>g[v]){
                    g[v]=g[u]+w;
                    pre[v]=i;
                }
            }
        }
    }
}
int main()
{
    all=0;
    init();
    cin>>n>>m;
    for(int i=1; i<=m; i++){
        cin>>u>>v>>w;
        addedge(u,v,w);
        addedge(v,u,w);
        all+=w;
    }
    bfs();
    for(u=n; u!=1; u=E[id^1].v){
        id=pre[u];
        if(E[id].w==0){
            E[id].w=E[id^1].w=2;
        }else{
            E[id].w=E[id^1].w=0;
        }
    }
    cout<<f[n]+all-2*g[n]<<endl;
    //cout<<edge_cnt<<endl;
    for(int i=0; i<edge_cnt; i+=2){
        if(!E[i].w) continue;
        cout<<E[i^1].v<<" "<<E[i].v<<" "<<E[i].w-1<<endl;
    }
    return 0;
}