codeforces 507E (dijkstra+優先佇列)
阿新 • • 發佈:2018-12-24
題目大意:給無向簡單連通圖的m條邊,求從頂點1到頂點n的最短路,同時使得最短路徑中標記為0的邊數與不在最短路徑中標記為1的邊數之和最小,輸出這些邊。
//可以設邊權為1,使用優先佇列,當前路徑長度小的優先,路徑長度相等時,最短路徑中標記為0的邊少的優先。
#include<bits/stdc++.h> using namespace std; #define maxn 100005 struct Edge { int x,y,z; }edge[maxn<<1]; struct Node { int v,dis,num,pre; }node[maxn]; struct cmp { bool operator() (Node &x,Node &y) { return x.dis>y.dis||(x.dis==y.dis&&x.num>y.num); } }; vector<int>g[maxn]; bool vis[maxn]; bool used[maxn<<1]; int n,m; priority_queue<Node,vector<Node>,cmp> Q; void solve() { Node temp=Node{1,1,0,-1}; int i; Q.push(temp); memset(vis,0,sizeof(vis)); while(!Q.empty()) { temp=Q.top();Q.pop(); if(vis[temp.v]) continue; vis[temp.v]=1; node[temp.v]=temp; if(temp.v==n) break; for(i=0;i<g[temp.v].size();++i) { int j=g[temp.v][i]; if(vis[edge[j].y]) continue; if(edge[j].z) Q.push(Node{edge[j].y,temp.dis+1,temp.num,j}); else Q.push(Node{edge[j].y,temp.dis+1,temp.num+1,j}); } } int ans=0; memset(used,0,sizeof(used)); i=temp.pre; while(i!=-1) { used[i]=1; i=node[edge[i].x].pre; } for(i=1;i<=m+m;i+=2) { if(used[i]||used[i+1]) { if(edge[i].z==0) ++ans; } else if(edge[i].z==1) ++ans; } printf("%d\n",ans); for(i=1;i<=m+m;i+=2) { if(used[i]||used[i+1]) { if(edge[i].z==0) printf("%d %d 1\n",edge[i].x,edge[i].y); } else if(edge[i].z==1) printf("%d %d 0\n",edge[i].x,edge[i].y); } } int main() { int i; cin>>n>>m; for(i=1;i<=m+m;i+=2) { scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z); edge[i+1].x=edge[i].y; edge[i+1].y=edge[i].x; edge[i+1].z=edge[i].z; g[edge[i].x].push_back(i); g[edge[i+1].x].push_back(i+1); } solve(); return 0; }